Core Java

Inheritance In Java

Introduction:

Inheritance is one of the core principles of Object Oriented Programming. It enables us to establish IS-A relationship between classes/objects and reuse existing code.

It is through the support of inheritance that we can extend a class from another. It’s kind of establishing a parent-child relationship among classes that relate to each other.

Let’s say, we have a Car class with a field color and a method drive(). What if later we wish to define an SUV (a kind of car)? One way would be to create an SUV class and define color and drive() for it along with its other members.  Inheritance in Java saves us from such a code duplication.

If we simply extend SUV from the Car class, our SUV will automatically have access to those members of Car. Note that by doing so, we’ll establish an SUV IS-A Car relationship.

Key Terms:

The vocabulary of inheritance usually involves using below terms interchangeably:

  • Parent/Child class or interface
  • Base/ Derived class or interface
  • Superclass/Subclass

Types of Inheritance:

  1. Single-Level Inheritance: A child class/interface extending from its parent
  2. Multi-Level Inheritance: A child class/interface extending from its parent which is again extending from its parent and so on
  3. Multiple Inheritance: It’s important to note that Java supports multiple-inheritance only through interfaces. The central idea is to have a child extending from multiple parents

Inheritance Types

What’s inherited?

A child inherits all the visible members of its superclass:

  • It may use any public or protected members of its parent
  • If both parent and child are defined in the same package, the child also inherits the default members of its parent
  • A child can’t inherit private members of its parent as they aren’t visible outside the class
  • Constructors are never inherited. A child class, however, can invoke its parent class constructor using super()

Inheritance for Classes:

Java allows us to extend one class from another using extends keyword:

class Car {
    
    String color = "Blue";
    
    public void drive() {
        System.out.println("Driving my car");
    }
}

class SUV extends Car {

    public void displayDetails() {
        System.out.println("My car is "+ color);
        drive();
    }
}

Note that we haven’t created an instance of Car in our SUV. Still, we’re able to invoke drive() method and access the property color in SUV class.  So our SUV has inherited those members from Car.

Java supports single-level and multi-level inheritance for both classes and interfaces. However, multiple-inheritance for classes isn’t allowed.

Inheritance for Interfaces:

Unlike Java classes, a Java interface can extend multiple interfaces:

interface Car {
    void drive();
}

interface Vehicle {
    void startIndicator();
}

interface SUV extends Car, Vehicle {
    void displayDetails();
}

In the above code, our SUV interface has three methods – drive(), startIndicator() and displayDetails(). Any class that implements SUV must provide an implementation for all three of them.

Class Implements Interface:

Java allows a class to implement an interface:

class Truck implements Vehicle {
    
    public void startIndicator() {
        System.out.println("Starting Truck's indicator");
    }
}

Please note that:

A class can extend a class. An interface can extend an interface. A class implements an interface

Also when implementing an interface, a class is bound to provide the implementation of the abstract methods defined in an interface. A class can implement multiple interfaces.

Multiple-Implementation Inheritance:

We already discussed that Java supports multiple-inheritance through interfaces.

Java 8 onwards, we can define the default implementation of the methods in an interface. Let’s consider a scenario:

interface Vehicle {
    default void startIndicator() {
        System.out.println("Starting indicator");
    }
}

interface Car {
    default void startIndicator() {
        System.out.println("Car :: Starting indicator");
    }
}

 

Now, what if I wish to a create an SUV class implementing both Vehicle and Car interfaces. What will the implementation of SUV‘s startIndicator() look like?

The answer to that is our code won’t compile for such scenarios. The reason being our Java compiler can’t decide which implementation to inherit.

//won't compile
class SUV implements Vehicle, Car {
    
}

For the above code to compile, we’ll have to override our startIndicator() method:

class SUV implements Vehicle, Car { 
    @Override
    public void startIndicator() {
        System.out.println("SUV :: Starting indicator");
    }
}

Conclusion:

In this article, we learned about Java Inheritance and its types. Note that we must always try to establish only justifiable IS-A relationships.

Be the First to comment.

Leave a Comment

Your email address will not be published. Required fields are marked *