Article Content
Recall of Java Inheritance
Consider the following class:
int a;
int b;
int add() {
return a + b;
}
}
This class has two properties: a and b. In Java, properties are called fields. This class has one method that adds two numbers, which are the field values. The name of the class is Cparent, with the preceding C, for Calculator. The following code segment in the main() method, outputs 5:
parent.a = 2;
parent.b = 3;
int rAdd = parent.add();
System.out.println(rAdd);
Consider the following class, which is the subclass of the above class (Cparent):
int c;
int multiply() {
return a * c;
}
}
Note the use of the keyword extends. This class has the field, c, and the method, multiply(). The class inherits the fields, ‘a’ and b, and the method, add(). However, if the field value for ‘a’ or b is to be used for this current instantiated object (child object), it still needs to be reassigned a value. For this class, the value of ‘a’ inherited is multiplied by the class’s field value of c. The name of this class is Cchild, with the preceding C, for Calculator. The following code segment in the main() method suits this class:
child.a = 2;
child.c = 4;
int rMult = child.multiply();
System.out.println(rMult);
The output is 8. Note that, though the field ‘a’ was inherited, it still had to be reassigned a value; in this case, the same value.
Consider the following class, which is the subclass of the above class, Cchild:
int d;
int divide() {
return a / d;
}
}
Note the use of the keyword extends. This class has the field, d, and the method, divide(). The class inherits the members, ‘a’, b, and add() from the Cchild class, which inherited them from the Cparent class. It also inherits the members, c, and multiply() from the Cchild class. However, if the field value for ‘a’ or b or c, from the parent or grandparent classes, is to be used for this current instantiated object (grandchild object), it still needs to be reassigned a value. For this class, the value of ‘a’ inherited is divided by the class’s field value of d. The name of this class is CgrandChild, with the preceding C, for Calculator. The following code segment in the main() method suits this class:
gChild.a = 2;
gChild.d = 2;
int rDiv = gChild.divide();
System.out.println(rDiv);
The output is 1. Note that, though the field ‘a’ was inherited, it still had to be reassigned a value; in this case, the same value, 2.
Use of the super Keyword
Field and super
In the above program, the value for the field, ‘a’ was set three times, once for the parent object, once for the child object, and once for the grandchild object. To avoid this resetting each time, the value of 2 can be assigned once, in the parent class implementation (definition) as follows:
int a = 2;
int b;
int add() {
return a + b;
}
}
This solves the problem of resetting for each descendant object. In the descendant classes, the field, ‘a’ is simply referred to (normally).
To access the value of an inherited field, the super keyword has to be used in the descendant class implementation of interest, as follows:
The following code segment shows how the name ‘a’ has been accessed, in a new Cchild implementation:
int p = super.a;
int c;
int multiply() {
return p * c;
}
}
The class, Cchild, now has its own name, p instead of ‘a’. And so the statement in the add() method,
is now,
In a similar way, the class implementation, CgrandChild can have ‘a’ replaced by q, as follows:
int q = super.a;
int d;
int divide() {
return q / d;
}
}
Note: Inheritance takes place in all descendant classes. The ‘a’ field and the add() method are inherited into the Cchild class and into CgrandChild class.
Method and super
Similarly, an inherited field can be accessed in the implementation of a descendant class; an inherited method can also be accessed in a descendant class, using the super keyword. The syntax is:
The implementation of the original Cchild class can be modified as follows:
int c;
int sum = super.add();
int multiply() {
return a * c;
}
}
Note that use of super. The inherited add() method is now seen as a “sum” in the implementation of Cchild. The field c, and the method, multiply(), are still there. A code segment for addition in the main() method that suits this modified Cchild class is:
The output is 5, assuming that the parent class was modified with:
int b = 3;
Constructor and super
The default constructor, which is not implemented, is inherited into every descendant class and does not have to be accounted for in the implementation of the descendants and in the main() method. However, once a parent class has a custom constructor, the rest of its descendants need to have a similar constructor. Consider the parent class, with a custom constructor, as follows:
int a, b;
public Cparent(int x, int y) {
a = x; b = y;
}
int add() {
return a + b;
}
}
The fields of ‘a’ and b are declared without assignment. The constructor does the assignment. The child class needs to have the same or a similar constructor. The corresponding child class for the original calculator hierarchy can be:
Cchild(int x, int y) {
super(x, y);
}
int c;
int multiply() {
return a * c;
}
}
The constructor here is the same as that of the parent. The body of the constructor here just has:
which just calls the constructor of the parent, with the arguments received. “super” here represents the parent class constructor. This is another use of super. There is no modification in this child constructor. The corresponding grandchild class for the original calculator hierarchy can be:
int d;
CgrandChild(int x, int y, int z) {
super(x, y);
d = z;
}
int divide() {
return a / d;
}
}
The constructor here is modified. It has the same x and y parameters and an extra parameter, z. z is to assign the value for d, the divisor. The body for the constructor begins by calling the constructor of the parent class. Then the field for the divisor is assigned. The following code segment in the main() method suits this class:
int rDiv = gChild.divide();
System.out.println(rDiv);
The output for this is 1.
Conclusion
Super will look for something in the immediate parent class. If it does not see it there, it will look for it in the grandparent class. If it does not see it there, it will look for it in the great grandparent class; and so on, until it either sees it or it does not see it. “super” is usually used within the implementation of a subclass. It is used for field, method, and constructor. The direct superclass is the parent class. The grandparent class is a superclass, but not the direct superclass. Next, the reader should understand the use of “super” with nested classes – see later.