Monday, December 26, 2016

How can inheritance be implemented in Java

Definitions:
Inheritance is the process in which a class can extend or inherit or derive another class and can reuse their property (data member & methods).

A class that is derived or inherited from another class is known as subclass or, derived class or, extended class, or child class. The class from which the subclass is derived is known as a super class or, base class or, a parent class.

As we know that Object is a top class in java class hierarchy, so obviously the Object class does not have any parent class, but except Object class all classes in java must have a one and only one super class (this is called single inheritance). If any class does not explicitly inherit any other class then it is implicitly inherited by Object class.

Classes can be inherited from a class which further inherited from other class and so on.. and at the top of this hierarchy the root class will always be the Object class.

Example: let’s have a scenario where a manufacturing company is having 2 types of supplier, one who supplies parts for their gas engine and another who supplies general items like computer, cubical, water, disposables etc. So, all suppliers need some common fields like name, address etc. and some specific fields related to their supplied product. We are going to put all common fields in parent class and specific fields to their child classes.

Supplier.java

public class Supplier {

    // 3 fields of Supplier class - declared as public and protected both for demo
    public String supplierName;
    public String supplierAddress;
    protected String supplierContact;
   
       public String getSupplierName() {
              return supplierName;
       }
      
       public void setSupplierName(String supplierName) {
              this.supplierName = supplierName;
       }
      
       public String getSupplierAddress() {
              return supplierAddress;
       }
      
       public void setSupplierAddress(String supplierAddress) {
              this.supplierAddress = supplierAddress;
       }
      
       public String getSupplierContact() {
              return supplierContact;
       }
      
       public void setSupplierContact(String supplierContact) {
              this.supplierContact = supplierContact;
       }

}

XYZLimited.java
//This is a gas engine part supplier
public class XYZLimited extends Supplier
{
       //2 local fields of XYZLimited
       public String partName;
       public String partGasEngineType;

      
       public String getPartName() {
              return partName;
       }

       public void setPartName(String partName) {
              this.partName = partName;
       }

       public String getPartGasEngineType() {
              return partGasEngineType;
       }

       public void setPartGasEngineType(String partGasEngineType) {
              this.partGasEngineType = partGasEngineType;
       }

}

ABCLimited.java

//This is a general supplier
public class ABCLimited extends Supplier {
       //2 local fields of ABCLimited
       public int cubicalSize;
       public String computerMonitorSize;
      
       public int getCubicalSize() {
              return cubicalSize;
       }

       public void setCubicalSize(int cubicalSize) {
              this.cubicalSize = cubicalSize;
       }

       public String getComputerMonitorSize() {
              return computerMonitorSize;
       }

       public void setComputerMonitorSize(String computerMonitorSize) {
              this.computerMonitorSize = computerMonitorSize;
       }
      
}


Implementation.java

public class Implementation {

       public static void main(String[] args) {

       XYZLimited partSupplier =  new XYZLimited();
       partSupplier.setSupplierName("Xyz Limited");
       partSupplier.setSupplierAddress("XYZ Street, New York, USA");
       partSupplier.setSupplierContact("+1 4444444444");
       partSupplier.setPartGasEngineType("Electric");
       partSupplier.setPartName("Valve Spring");
             
       ABCLimited generalSupplier = new ABCLimited();
       generalSupplier.setSupplierName("Abc Limited");
       generalSupplier.setSupplierAddress("ABC Street, wisconsin, USA");
       generalSupplier.setSupplierContact("+1 8888888888");
       generalSupplier.setComputerMonitorSize("18 Inch");
       generalSupplier.setCubicalSize(5);
             
       System.out.println("Details of part material supplier: ");
       System.out.println("Supplier Name: " + partSupplier.getSupplierName());
       System.out.println("Supplier Address: " + partSupplier.getSupplierAddress());
       System.out.println("Supplier Contact: " + partSupplier.getSupplierContact());
       System.out.println("Gas Engine Type: " + partSupplier.getPartGasEngineType());
       System.out.println("Part Name: " + partSupplier.getPartName());

             
       System.out.println("\nDetails of part general supplier: ");
       System.out.println("Supplier Name: " + generalSupplier.getSupplierName());
       System.out.println("Supplier Address: " + generalSupplier.getSupplierAddress());
       System.out.println("Supplier Contact: " + generalSupplier.getSupplierContact());
       System.out.println("Gas Engine Type: " + generalSupplier.getComputerMonitorSize());
       System.out.println("Cubical Size: " + generalSupplier.getCubicalSize());
             
}

}

Output:



Hierarchical representation of above example:



Characteristics of inheritance:
  1. A private data member or method cannot be inherited by sub class. However if there is a public method in parent class which further access its private members then such methods can be directly used from its child class.
  2. Only protected and public members can be inherited.
  3. A class cannot have more than one parent class, in short multiple inheritance is not allowed in java. (Available in C++). However we can achieve indirectly using "interface" concept which we will discuss in detail in next to next chapter.
  4. Parent class can always store reference of its child class but vice versa is not possible.
  5. e.g.
    Supplier supplier1 = newSupplier();             //Correct
    Supplier supplier2 = newXYZLimited ();          //Correct
    XYZLimited xyzSupplier1 = newXYZLimited();      //Correct
           XYZLimited xyzSupplier2 = newSupplier();        //Incorrect
  6. In sub class the inherited members can be used directly just like its local members.
  7. We can declare a field in sub class with same name as declared in super class, but this is not recommended.
  8. We can declare new fields in sub class which are not in super class (e.g. cubicalSize in above example).
  9. We can write a new instance method in sub class with same signature (return type, name, parameters) as the one in super class, this process is known as method overriding.
  10. A sub class constructor can call super class constructor using “super” keyword.
  11. A nested class inside parent class has access to all private members (field & methods), and if that nested class is either public or protected then the child class can access it directly, thus the private members are accessed indirectly through inner class of parent. We will discuss about nested class in later chapters.

Advantages of inheritance
  1. Reusability – by reusing the fields or methods we save the wastage of memory. In our example we need not to declare supplierName, supploerAddress & supplierContact 2 times in XYZLimited & ABCLimited. This is the beauty of inheritance.
  2. Reduced complexity of code.
  3. Dynamic binding can be achieved using inheritance.

Constructor in Inheritance:

Constructor plays an important role in inheritance, constructor overriding is allowed in java. There are a set of rules and regulations while implementation constructor in inheritance. Let’s take this example:

Create a file A.java:

class A
{
      A()
      {
            System.out.println("Constructor A");
      }
}
class B extends A
{
      B()
      {
            System.out.println("Constructor B");
      }
}
public class C extends B
{

      C()
      {
            System.out.println("Constructor C");
      }

      C(int x)
      {
            System.out.println("Parameterized Constructor C - " + x);
      }

      public static void main(String[] args)
      {
            new C();          //this is Anonymous object (Will discuss later)
            new C(10);
      }
}

Output:



Rule 1:
Whenever a child class constructor is executed, it has to execute the immediate parent class constructor first, then itself. If for any reason the child class is not able to execute its parent’s constructor then it cannot execute its own constructor.
In this example class A’s constructor will execute Object class constructor.
If we do not extend a class then it implicitly extend Object class.
Quick Question – why it is required to execute parent class constructor first? How it is implemented internally.

Answer – because child class does have ability to inherit all of their data members and methods but not the constructors. For example, if we have written database connection code in B class constructor, then we can never get it explicitly from C class constructor, and all database connection code will be required to be re written in C class constructor. This rule is defined for reuse of constructor.

We can call the super class constructor explicitly using super keyword, but it should be the first line in any constructor. In above example compiler automatically add super keyword in each constructor. Like this:

      C()
      {
            super()
            System.out.println("Constructor C");
      }

      C(int x)
      {
            super(); 
            /*in this case B must have a constructor with int
            argument otherwise compiler error */
            System.out.println("Parameterized Constructor C - " + x);
      }

Rule 2:
Compiler always adds a default constructor in each class if no any constructor is kwritten in it. In case a parameterized constructor is defined in parent class and child class is defining default constructor this compiler will throw error as it will be unable to find default constructor in parent class.
For example:

class B
{
      B(int x)
      {
            System.out.println("Constructor B");
      }
}
public class C extends B
{

      C()
      {
            super();  //Line No 13
            System.out.println("Constructor C");
      }

      public static void main(String[] args)
      {
            new C();
            new C(10);
      }
}

Compiler will give following error at line No 13 in above program:
Error: The constructor B() is undefined

We can resolve above issue by either adding a default constructor in class B or by replacing super() with super wih an int argument in class C constructor.

No comments:

Post a Comment