Friday, January 22, 2016

Topic 23: Inheritance in Java

  • Using inheritance, we can create a general class that defines traits common to a set of related items. This class can then be inherited by other more specific classes, each adding those things that are unique to it. In the terminology of Java, a class that is inherited is called a superclass. The class that does the inheriting is called a subclass.

  • To inherit a class, we use extends keyword. For ex, the following code fragment creates a superclass called A and a subclass called B.  

// Create a superclass.
class A {
int i, j;

void showij()
{
System.out.println("i and j: " + i + " " + j);
}
}

// Create a subclass by extending class A.
class B extends A
{
int k;

void showk()
{
System.out.println("k: " + k);
}

void sum()
{
System.out.println("i+j+k: " + (i+j+k)); //Can access members of superclass
}
}

//Class containing main()
A superOb = new A();
B subOb = new B();

// The superclass may be used by itself.
superOb.i = superOb.j = 20;
superOb.showij();
System.out.println();

/* The subclass has access to all public members of its superclass. */
subOb.i = subOb.j = subOb.k = 9;
subOb.showij();
subOb.showk();

System.out.println();
subOb.sum();


  • The general form of a class declaration that inherits a superclass is shown here:

class subclass-name extends superclass-name
{
// body of class
}

  • We can only specify one superclass for any subclass that we create. We can create a hierarchy of inheritance in which a subclass becomes a superclass of another subclass. However, no class can be a superclass of itself.

  • A subclass has access to all the members of its superclass, except those declared as private. 

  • A reference variable of a superclass can be assigned a reference to any subclass derived from that superclass. For ex, consider the following: 

    Box is a superclass of BoxWeight. Box has members width, height and depth as instance variables and volume() as instance method. BoxWeight has weight as instance variable.

//Inside class containing main()
BoxWeight weightbox = new BoxWeight(3, 5, 7, 8.37);
Box plainbox = new Box();


// assign BoxWeight reference to Box reference
plainbox = weightbox;

// OK, volume() defined in Box
System.out.println("Volume of plainbox is " + plainbox.volume());

//The following stmt is invalid because plainbox does not define a weight member
//System.out.println("Weight of plainbox is " + plainbox.weight);

Important note: It is the type of the reference variable and not the type of the object that it refers to, that determines what members can be accessed. That is, when a reference to a subclass object is assigned to a superclass reference variable, we will have access only to those parts of the object defined by the superclass.


Using super


  • If the subclass constructor initializes the instance variables of superclass, this will duplicate the code written in superclass constructor. This is inefficient, and also it implies that a subclass must be granted access to superclass members. Cases where superclass instance variables are private, subclass constructor cannot access the superclass instance variables. To overcome this limitation, Java provides us with super keyword.

  • Whenever a subclass needs to refer to its immediate superclass, it can do so by use of the keyword super. super has two general forms:

  • The first calls the superclass’ constructor.

  • The second is used to access a member of the superclass that has been hidden(i.e. Private).

  • A subclass can call a constructor defined by its superclass by use of the following form of super:

    super(arg-list);

Here, arg-list specifies any arguments needed by the constructor in the superclass. super( ) must always be the first statement executed inside a subclass’ constructor.

Constructors can be overloaded and therefore, super( ) can be called using any form defined by the superclass. The constructor executed will be the one that matches the arguments.

When passing object to the superclass constructor, we will pass the subclass object. This is because the superclass variable can be used to reference any object derived from that class.

// construct clone of an object
SubclassConstructor(Subclass ob) // pass object to constructor
{
super(ob);
subclassvar = ob.subclassvar;
}

  • The second form of super is used to access a member of the superclass that has been hidden(i.e. Private). This usage has the following general form:

super.member

Here, member can be either a method or an instance variable.

This second form of super is most applicable to situations in which member names of a subclass hide members by the same name in the superclass. For ex,

class superClass
{
int i;
}
class subClass extends superClass
{
int i; // this i hides the i in superClass
subClass(int a, int b)
{
super.i = a; // i in superClass
i = b; // i in subClass
}
void show()
{
System.out.println("i in superclass: " + super.i);
System.out.println("i in subclass: " + i);
}
}
//Inside class containing main()
subClass subOb = new subClass(1, 2);
subOb.show();

  • super( ) always refers to the constructor in the closest superclass. In a class hierarchy, if a superclass constructor requires parameters, then all subclasses must pass those parameters “up the line.” This is true whether or not a subclass needs parameters of its own.

  • When a class hierarchy is created, constructors are called in order of derivation, from superclass to subclass. This order is the same whether or not super( ) is used in subclass constructor. If super( ) is not used, then the default or parameterless constructor of each superclass will be executed.

    If we think about it, it makes sense that constructors are executed in order of derivation. Because a superclass has no knowledge of any subclass, any initialization it needs to perform is separate from and possibly prerequisite to any initialization performed by the subclass. Therefore, it must be executed first.

  • In a class hierarchy, when a method in a subclass has the same name and type signature as a method in its superclass, then the method in the subclass is said to override the method in the superclass. 

    When an overridden method is called from within a subclass, it will always refer to the version of that method defined by the subclass. The version of the method defined by the superclass will be hidden. 

    If we wish to access the superclass version of an overridden method, we can do so by using super.

    Method overriding occurs only when the names and the type signatures of the two methods are identical. If they are not, then the two methods are simply overloaded.

  • Dynamic method dispatch is the mechanism by which a call to an overridden method is resolved at run time, rather than compile time. Dynamic method dispatch is important because this is how Java implements run-time polymorphism. 

    A superclass reference variable can refer to a subclass object. Java uses this fact to resolve calls to overridden methods at run time. Here is how. When an overridden method is called through a superclass reference, Java determines which version of that method to execute based upon the type of the object being referred to at the time the call occurs. Thus, this determination is made at run time. When different types of objects are referred to, different versions of an overridden method will be called. In other words, it is the type of the object being referred to (not the type of the reference variable) that determines which version of an overridden method will be executed.

// Dynamic Method Dispatch
A a = new A(); // object of type A
B b = new B(); // object of type B where B is subclass of A

A r; // obtain a reference of type A

r = a; // r refers to an A object
r.callme(); // calls A's version of callme

r = b; // r refers to a B object
r.callme(); // calls B's version of callme

 

Click for NEXT article.

 

Please feel free to correct me by commenting your suggestions and feedback.

No comments:

Post a Comment