Let’s Do It PL
What is “Inheritance”?
Object-Oriented Programming is built on 4 big principles and one of them is Inheritance. Thanks to this mechanism, developers can easily create objects that have a relationship between them. Also, Inheritance is a very important key to understand other principles.
Object-Oriented Programming started a new era in the coding world. After it was found, developers became capable of putting anything in the real world into the code world. Even we can fly some birds into our codes.
Let’s start with putting a parrot inside of our codes. We can simply create an object named Parrot and we can just create some methods on behalf of its actions and some variables on behalf of its attributes. We can declare a color variable in that object and decide its color and/or create a method named fly() and it is done. Our parrot is ready to fly by just calling the fly() method.
What about we want to create also an object named Sparrow? We should also do almost the same things when we create the Parrot object. We will add a color variable and a fly() method that almost all birds have. Now, we have 2 objects that have some common variables and methods. Can we say they do not have any relationship? No, right? As a human, we know they both are birds and share some common attributes but the computer cannot understand that connection between them. For creating this “Parrot-Bird” relationship, we use Inheritance.
For achieving that, we are using the “extends” keyword simply adding after class name and adding inherited class name.
public class Parrot extends Bird{
}
That’s it. Now our computers also know Parrot is a Bird and it can do whatever Bird can do.
IS-A Relationship
Simply, Inheritance lets us create an IS-A relationship between objects. For example:
- Parrot IS-A Bird
- Whale IS-A Mammal
- Rose IS-A Flower
- Chess IS-A Game
IS-A relationship is also named a “parent-child” relationship. But why we are creating these relationships? Actually, we are gaining many benefits from those relations. Let’s explain verbally first. A Parrot can fly because it IS-A Bird, right? So, if the Parrot class extends the Bird class, it means the Parrot class has the same methods and variables too. Let’s show that in an example:
public class Bird { String color; public void fly(){
System.out.println("Bird is flying in the sky freely");
}
public void tweet(){
System.out.println("tweet");
}
}
We have a class named Bird which has a color variable and fly() and tweet() methods. Let’s create a Parrot class too:
public class Parrot extends Bird{
public void talk(String word){
System.out.println(word);
}
}
As we see, there is a talk() method but no fly() method in the Parrot class so is that mean Parrot cannot fly and only talk? No, because it inherits that method from Bird class or simply it has that method because Parrot IS-A Bird. Let’s create an object and check it can fly or not?
public static void main(String[] args) {
Parrot parrot = new Parrot();
parrot.fly();
//Output: Bird is flying in the sky freely
}
There are no compiler errors or wrong output so it is perfectly fine because Parrot IS-A Bird thanks to the relationship that we create between them.
Superclass and Subclass
We successfully created classes that use Inheritance. In the coding language, we call these classes with different names. “Subclass” name is given to the class that inherits some methods from another class and the class that is inherited by that subclass is named as “Superclass”. Then in our example, the Bird class is a superclass and the Parrot class is a subclass. So, in simple words:
Inheritance is a mechanism that allows subclasses to inherit methods and variables from superclasses and use them.
Through Inheritance, a subclass can inherit all members of a superclass like variables, methods, and nested classes but cannot inherit constructors because constructors cannot count as a member of a class. If we want to do that we should invoke the superclass’s constructor inside the subclass’s constructor with the “super()” keyword. Let’s do this in an example to understand better:
public class Bird {
public Bird() {
System.out.println("This is a bird");
}
public Bird(String color){
System.out.println("This is a " + color + " bird");
}
}public class Parrot extends Bird{
public Parrot(String color){
super(color);
}
}
The Parrot class’s constructor has super(color) so it invokes the Bird class’s one-parameter constructor by sending the color variable as a parameter. So we created a Parrot class and used the Bird class’s one-parameter constructor. Let’s create a Parrot object and check what will happen:
Parrot parrot = new Parrot("yellow");//Output: This is a yellow bird
We could also write super() instead of super(color) to call the no-parameter constructor of the Bird class.
Private Fields and Final Class
There are some situations that we don’t want to inherit some variables or methods, moreover, we need a class that cannot be inherited by any subclass. As we know from the Encapsulation principle, private variables or methods cannot be used outside of their classes. So it means cannot be inherited too. If we want to keep away class members from inheritance we should change their access modifiers to private, or maybe default or protected depending on the situation.
A class cannot be private because a private class is cannot be reachable which makes it useless. So if we try that, it shows us an error like “private is not allowed here”. Then, how can we avoid inheritance at the class level? The solution is creating a “Final Class” or simply making that class’s access modifier to final. With that, that class becomes a non-inheritable class.
final class Bird {
}
public class Parrot extends Bird{ //compiler error shows this line
}
If we do that, we will get an “error: cannot inherit from final Bird” message in the console.
Inheritance Types
Inheritance can be done in different ways. Let’s check them out one-by-one.
1-Single Inheritance
If a superclass is inherited by only one subclass, this is called “Single Inheritance”. We used this inheritance type from the beginning so it should be clear now.
2-Multilevel Inheritance
Being a superclass doesn’t mean, that class cannot be a subclass. If a superclass of a subclass inherits another class, it is called “Multilevel Inheritance”.
public class Animal{
}
public class Bird extends Animal{
}
public class Parrot extends Bird{
}
In the example, we see a Parrot class that extends Bird, on top of that the Bird class extends Animal class. So we have a “grandparent-parent-child” relationship here but in Java, the child class cannot directly access the grandparent class’s members.
3-Hierarchical Inheritance
If a superclass has more than one subclass, it is called “Hierarchical Inheritance”.
public class Bird{
}
public class Parrot extends Bird{
}
public class Sparrow extends Bird{
}
In this inheritance type, both Sparrow and Parrot classes can inherit all members of Bird and use them but cannot access each others’.
4-Multiple Inheritance
If a subclass has more than one superclass, this is called “Multiple Inheritance” but this inheritance type can only achievable by using interfaces. Java is not supporting Multiple Inheritance to reduce complexity and to simplify the language.
“instanceof” keyword
Sometimes we can need information about inheritance like “is Parrot a Bird?”. To asking this, we use the “instanceof” keyword. This action returns a boolean value that is true or false.
System.out.println(parrot instanceof Bird);
//Output: true
Summary
Inheritance makes our codes reusable which is one of the goals of Object-Oriented Programming. We can just use Inheritance to reuse other classes’ methods and variables to avoid rewriting them. Also, Inheritance supports other OOP principles like Abstraction and Polymorphism very much and this situation makes Inheritance the key point which connects all principles.