In a class hierarchy, A subclass can contain a method with the same signature and return type as in its superclass, then the method in the subclass is said to override the method in the superclass. However in certain situations, the subclass need to modify the implementation (code) of a method defined in the superclass without changing the parameter list. This is achieved by overriding or redefining the method in the subclass.
To override a subclass’s method, we simply redefine the method in the subclass with the same name, same return type and same parameter list as its superclass counterpart. When the method with the same name exists in both the superclass as well as in the subclass, the object of the subclass will invoke the method of the subclass, not the method inherited from the base class.
Now the question arises that can we invoke the overridden method of the superclass from the-subclass. The answer is yes and it is possible in Java using the super keyword followed by a dot operator and the overridden method along with the list of arguments enclosed in parentheses. Its syntax is
super.overriddenMethod(arguments) ;
The following program illustrates the concept of method overriding.
class Person { private String name; private int age ; Person(String n,int pAge) { name = n; age=pAge; } public String toString() { return("Name : "+ name+"\n"+ "Age : "+age+"\n"); } } class Student extends Person { private int rollno; private String stuClass ; private double percentage; Student(int rno,String n,int page,String c,double p) { super(n,page); //call superclass constructor rollno = rno; stuClass=c; percentage = p; } //override toString()method public String toString() { return("Rollno : "+ rollno +"\n"+ super.toString() +"Class : "+stuClass +"\n"+"Percentage : "+percentage); } } class OverridingMethods { public static void main(String[] args) { Student s=new Student(1,"Dinesh Thakur",35,"MCA",90.5); System.out.println(s.toString()); } }
Note: Overriding is different from overloading, In overloading, two methods have the same name but different parameter lists but in overriding, the methods have the same name and same parameter lists. The methods which are declared static in the superclass can’t be overriden by the superclass.
We’ll be covering the following topics in this tutorial:
Access Modifiers for Overriding Methods
The access modifier of the superclass method decides what the access modifier of the overriding subclass method can be. The table shows the relationship between the access modifier of a superclass method and the corresponding overriding method in the subclass. If the access modifier of the superclass method is protected, the overriding method in the subclass can only be protected, or public-it cannot be private. The reason for this is that an overriding method in the subclass cannot be less visible than the corresponding method in the superclass. The relationships for the package private and public access modifiers also shown in the table. If the access modifier of the superclass method is private, the method not inherited by the subclass, and thus it cannot be overridden in the subclass.
The following example explains, in more detail, how the modifiers can be used.
Consider two classes Bank and OnlineBank, where OnlineBank is a subclass of Bank.Only the method declarations in these two classes are shown here:
class Bank {
public void deposit(float amount) {}
protected void withdraw(float amount) {}
void name() {};
private void update() {};
}
class OnlineBank extends Bank {
private void deposit(float amount) {}
private void withdraw(float amount) {}
protected void name() {}
private void update() {}
}
Pick out the overriding methods in OnlineBank.Using above Table, explain which access modifiers in OnlineBank are incorrect and result in an error.
Solution:
class OnlineBank extends Bank {
private void deposit(float amount);// error!
private void withdraw(float amount);// error!
protected void name();// overrides method name in Bank
private void update();// does not override method update in Bank
}
The method deposit cannot have an access modifier of private. The reason is that, according to Table, if a method declared as public in a superclass, the overriding method should also be public in the subclass. Therefore, the deposit should be made public. Similarly, withdraw also has an incorrect access modifier of private. This method is declared as protected in Bank, and thus it can have access modifiers of protected or public only. The method update declared as private in Bank, and it is not visible to OnlineBank.Therefore, update in OnlineBank does not override update in Bank.
Covariant Return Types
Recall that an overriding method has the same return type as the method in its superclass. However, an exception exists when the return types are different. These return types are called covariant return types, and they differ in that the return type of the overriding method can be a subclass of the return type of its superclass method. We explain this with an example.
Consider four classes Animal, Goat, Zoo, and PettingZoo, where Goat derived from Animal, and PettingZoo derived from Zoo. The class Zoo has a method called getAnimal with the return type Animal:
public class Zoo {
private Animal myAnimal;
public Animal getAnimal (){
return myAnimal;
}
}
The getAnimal method in PettingZoo has a return type of Goat:
public class PettingZoo extends Zoo {
private Goat billy;
public PettingZoo() {
billy = new Goat();
}
// A return type of Goat is allowed
// since Goat is A subclass of Animal.
public Goat getAnimal(){
return billy;
}
}
The return type of getAnimal is Goat, which does not match the return type of Animal in the superclass method. However, no error exists, because Goat is a subclass of Animal. Therefore, the getAnimal method of PettingZoo overrides that of Zoo correctly. On the other hand, if the return type of the subclass method were different and not a subclass of the return type of the superclass method, it would be flagged as a compilation error.
Using the super Keyword
The subclass can call the overridden method in its superclass by using a special keyword called super. super keyword has two general forms:
(i) Calls the superclass constructor.
(ii) To access a member of the superclass that has been hidden by a member of a subclass.
(i) Using super to call superclass constructor
A subclass can call a constructor method defined by its superclass by using the super keyword.
super( argument.list );
Where,
argument.list – specifies any parameters needed by the constructor in the superclass.
Note: The argument list in the super call must match the order and type of the inheritance variables declared in the superclass.
(ii) Accessing a member of the super class that has been hidden by a member of a subclass.
A class can access a hidden member variable through its superclass.
The general form is
super.member
Here, member can be either a method or an instance variable.
super.varName;
super.methodname(parameter_list);
Here, varName is the name of the variable in the superclass. methodname is the name of the overridden method. Parameter_list is the list of arguments(optional). super keyword accesses the superclass variable and constructs a subclass by using the same variable name.
The next example shows why this keyword is useful, and how it can be used.
Suppose that we have a class called PieRecipe that contains a method called getDirections. This method describes how to make the crust of a pie:
package inheritance;
public class PieRecipe {
public void getDirections(){
System.out.println(“To prepare crust, rollout dough and chill in pie pan.”);
}
}
The class BlueberryPieRecipe extends the class PieRecipe. It contains an overriding method called getDirections that describes how to make the filling for the pie:
package inheritance;
public class BlueberryPieRecipe extends PieRecipe {
// overriding method in BlueberryPieRecipe
public void getDirections() {
System.out.println(“To prepare filling, combine blueberries, flour, lemon juice, and sugar and put in the pie pan, then cover with extra dough and bake.”);
}
}
There is a problem with BlueberryPieRecipe-its getDirections method only describes how to make the filling and not the crust. The getDirections method in PieRecipe describes how to make the crust, but this method is overridden and therefore is not inherited by BlueberryPieRecipe. This problem can be easily resolved by using the keyword super. The overridden method in PieRecipe can be accessed in the subclass using the following method:
super.getDirections();
The getDirections method in BlueberryPieRecipe is modified as shown here:
// modified method in BlueberryPieRecipe
public void getDirections() {
super.getDirections();
System.out.println(“To prepare filling, combine blueberries, flour, lemon juice, and sugar and put in the pie pan, then cover with extra dough and bake.”);
}
Write a main method to test the getDirections method in BlueberryPieRecipe:
public static void main(String[] args) {
PieRecipe r = new BlueberryPieRecipe();
r.getDirections();
}
The directions for both the crust and the filling are printed out when the program is run:
To prepare crust, rollout dough and chill in pie pan.
To prepare filling, combine blueberries, flour, lemon juice, and sugar and put in the pie pan, then cover with extra dough and bake.
Hidden fields can also be accessed in the subclass by using super. Suppose that BlueberryPieRecipe contains a field called ingredients that hides this field in PieRecipe. Then the hidden field can be accessed in BlueberryPieRecipe using super. ingredients. Remember, though, that in general, fields should not be hidden.