Interface and Inheritance in Java: Inheritance
When a class extends another class it’s called inheritance. The class that extends is called sub class while the class that is extended is called super class. Any class in java that does not extend any other class implicitly extends Object class.
In other words every class in java directly or indirectly inherits Object class.
By means of inheritance a class gets all the public, protected properties and methods of the super class no matter which package the sub class is present in. If the sub class is present in the same package as that of super class then it gets the package private properties and methods too. Once the sub class inherits the properties and methods of super class, it can treat them as if it defined them.
By using inheritance you can reuse existing code. If you have an already written class (but no source) and it lacks some features then you don’t have to write everything from scratch. Just extend the class and add a new method that satisfies your needs.
Note:
Private methods and properties are not inherited. However, if the super class has a private variable and a public method that uses the variable then the variable is made available inside the method in the sub class. You should also note that constructors are never inherited.
How to Extend
Use extends keyword to inherit the super class-
class A{
//properties and methods of A
}
class B extends A {
}
Note: A class can inherit only one class. Multiple inheritance is not supported in Java.
Method Overriding And Hiding
When a sub class defines a method that has same signature and return type (or compatible with return type of super class method) it is called method overriding.
Example:
class A{
int x;
public void printIt(){
System.out.println(“method in class A”);
}
}
class B extends A{
public void printIt(){
System.out.println(“method in class B”);
}
}
class Test{
public static void main(String[] args){
A a=new B();
a.printIt(); // prints “method in class B” without quotes
}
}
Here class B extends class A and overrides the method printIt()
. So, when we run the above code the method that gets called is printIt()
of class B. By overriding printIt()
defined in class A, class B can provide a different implementation to it. Still it can access the super class version of the method by using super keyword.
Example:
class B extends A{
public void printIt(){
super.printIt();
System.out.println(“method in class B”);
}
}
Note:
In the previous example we have used the reference of type A and object of B. But whose printIt()
method will be called is not decided during compilation time. Java waits till the runtime of the program and checks which object the reference is pointing to. In this case the object is of class B. So, it’s B’s printIt()
method which is getting executed. This is called dynamic method dispatch or virtual method invocation.
Now let’s assume class A has a static method printStatic
and class B, which is a sub class of A, defines a static method having same signature as that of A’s printStatic
. This is a case of method hiding.
Example:
class A{
public static void printStatic(){
System.out.println("In A");
}}
class B extends A{
public static void printStatic(){
System.out.println("In B");
}
}
class Test{
public static void main(String[] args){
A a=new B();
a.printStatic(); // prints “In A” without quotes
//We can also call like this A.printStatic()
}
}
In this case at compilation time Java will look for the reference type and not the object that is being pointed to. Here, the reference type is A. So, printStatic()
of class A is executed.
Casting Objects
Let’s take the example where class A is super class and class B is the sub class. We already know that it is possible to create an object of class B and assign it to a reference of type A. But by doing this you will be able to call the methods that are defined in class A only. In order to call the methods that are defined by class B you need to cast the reference.
Example:
A a=new B();
a.methodSpecificToB(); // illegal
B b=(B)a;
b.methodSpecificToB(); //legal
Constructor Chaining
When we instantiate a sub class the super class constructor also runs. It happens by means of a call to super()
. When we don’t explicitly call super()
inside a sub class constructor the compiler implicitly puts super()
as the first statement in each of the overloaded constructors (like methods, constructors can also be overloaded) assuming that a call to this()
is not present in the constructors.
If you don’t define a constructor for your class the compiler creates a default constructor (which is no arg) and places a call to super()
. The only condition is that your super class should have a no arg constructor or else it will produce a compile time error. If you have a super class that does not have a no arg constructor then you should call super()
with appropriate parameters from your sub class constructor.
The concept will be clear from the following example:
class A{
A(){
System.out.println(“Constructor of A running”);
}
}
class B extends A{
B(){
//a call to super() is placed here
System.out.println(“Constructor of B running”);
}
}
public class Test{
public static void main(String[] args){
new B();
}
}
Output
Constructor of A running
Constructor of B running
Note: The sub class constructor is called first, but it’s the super class constructor that finishes executing first.
Summary
- A class can extend only one class.
- Every class is a sub class of Object directly or indirectly.
- A super class reference can refer to a sub class object.
- If reference is super class and object is of sub class then calling an instance method on it will result in execution of the method defined in sub class.
- An overridden method has same signature and return type (or compatible with the return type) as that of super class method.
- We can hide a static method defined in super class by defining a static method having same signature or return type (or compatible with the return type) as that of super class method.
- When a sub class constructor runs the super class constructor also runs. This is called constructor chaining.