Skip to content

Inheritance

Java allows a Class to extend the content of another Class to reduce code redundancies. This coding practice is called Inheritance.  It is one of the fundamental Object-oriented techniques that aim to reduce the code we write in our project.

In this code note, we will cover following topics:

  • DRY Principal
  • Inheritance Basics
  • Method Overriding
  • Controlling Inheritance
  • Inheritance & Constructor
  • Summary



› DRY Principal

One of the frowned-upon practices in software development is writing repeating code. So much so that there is a programming principle aimed at preventing code redundancies called Don't Repeat Yourself.

"Repeating Code

The Don't Repeat Yourself principle mandates avoiding duplicate writing code as much as possible.   It is one of the fundamental principles of software development aimed at reducing code repetition.  Inheritance is one of the most effective and straightforward ways to reduce redundant code in your project.

Let us understand reducing code redundancies by looking at these two separate Class models:

As you can see, both class model contains duplicate fields and methods, as shown in red. This code redundancy is common as we often have to represent similar data types in our project. However, creating a Class that contains duplicate fields and methods violates the DRY principle.

Using inheritance, we can prevent DRY principle violations. In Java, the inheritance gives us the ability seamlessly copy & paste the fields and methods of one Class to another Class, which results in unique codebase.

As you can see, inheritance extracted these repeating Fields and Methods into another class called BankAccount. Because of this, there are no more repeating codes, and an is-a relationship has formed between super and subclasses.

For example:

  • CheckingAccount is-a BankAccount
  • SavingAccount is-a BankAccount

If we make any changes to the BankAccount class, the changes will be automatically reflected in the CheckingAccount and SavingAccount classes.



› Inheritance Basics

Let's go over some inheritances key points:

  • Java class can be inherited by another class by using the extends keyword.
  • The class we are trying to inherit is called Parent class or Super class.
  • The class that inherited fields and methods from the parent class is the Child class or Sub class.
  • Methods that are unique to the Child class are known as specialization.
  • In the Child class, we can override the inherited methods from the Parent class.

Let's understand inheritance key points with code examples. Consider the following class models.

The Peter class is a parent class where all of its public fields and public methods will be inherited.

public class Peter {
    //-- Fields --//
    String familyName = "Griffin";

    //-- Method --//
    public void sing(){
        System.out.println("Bird is The Word!");
    }

    public void fight(){
        System.out.println("Fighting with Yellow Rooster");
    }
}

The Stewie class is a child class where it inherits all the public fields and public methods form another class.

public class Stewie extends Peter {
    //-- Fields --//
    String[] toys;

    //-- Method --//
    @Override
    public void fight(){
        // Content of fight() method are changed 
        // to Stewie's own implementation 
        System.out.println("Fighting with Lois");  
    }

    // This method is unique to child class
    // this is known as Specialization
    public void timeTravel(){
        System.out.println("Time traveling with Brian");
    }
}

Usage: Type these out in the main() method.

// ------ CODE SEGMENT -------------// // ---------- EXPLANATION -----------------------------//
Peter peter = new Peter();             // Peter object
System.out.println(peter.familyName);  // Griffin
peter.sing();                          // Bird is The Word!
peter.fight();                         // Fighting with Yellow Rooster

Stewie stewie = new Stewie();          // Stewie object that extends Peter
System.out.println(stewie.familyName); // Griffin
stewie.sing();                         // Bird is The Word!          <- Same as Peter object
stewie.fight();                        // Fighting with Lois         <- Method Override
stewie.timeTravel();                   // Time traveling with Brian  <- unique to Stewie

Peter son = new Stewie();               // Stewie object reference with Peter Type Variable
System.out.println(son.familyName);     // Griffin
son.sing();                             // Bird is The Word!
son.fight();                            // Fighting with Lois        <-- Method Override
son.timeTravel();                       // ERROR! Will not run. 



› Method Overriding

From the above examples, we know that objects of a subclass can also access methods of its superclass.   What happens if the same method is defined in both the superclass and subclass?  For example, the same fight() method exists in both classes.  The only difference is their method code content. This is known as Method Overriding.

// fight() methods in Peter class
public void fight(){
    System.out.println("Fighting with Yello Big Chicken");
}

// fight() methods in Stewie class
@Override
public void fight(){
    System.out.println("Fighting with Lois");   
}

Method overriding allows the Subclass to have its version of the method implementation for the method it shares with its parent class.

Overriding is a feature that allows a subclass or child class to provide a specific implementation of a method that is already provided by the parent class—allowing it has its own unique implementation.

Even though it is optional, You should label your overriding method with @Override annotations to clarify that it is performing method overridden.  It is explicit programming, and everybody would appreciate you.

Object Class

The Object class is the root of the Java class hierarchy.  Every class you make in Java inherits an Object class directly or indirectly behind the scene.  Thanks to the code inside this class, we can create an object from our own class after designing them.

Peter's class is directly inheriting the Object class behind the scene.  Stewie's class, extending Peter's class, is indirectly extending the Object class.

Object class has some practical methods you should remember.  Every single class in Java has these methods.

Method Name Description
clone() Create a new object instance that duplicates the current instance.
hashCode() Get a hash code ( ID ) for the current instance.
getClass() Return type information for the current instance.
finalize() Handle special resource cleanup scenarios.
toString() Return text representing the current instance.
equals() Compare another object to the current instance for equality.



› Controlling Inheritance

Java offers two ways of controlling inheritance.  We can prevent our class from being inherited, and also, we can force our class to be used only for inheritance.

Prohibiting Inheritance

Use final keyword. If you mark your class as final, that class cannot be used for inheritance.

1
2
3
4
5
6
7
8
public final class String {
    // string class is the only class 
    // that cannot be inherited out of the package.
}

public class AmazingString extends String{    // <=== This is programming error!  String is final class,
    //...                                     //      it cannot be inherited
}

If you mark your method as final, that method cannot be overridden in inheritance.

// SUPER CLASS 
public class Parent {
    // --- Fields ---
    // --- Methods --
    public final void singing(){
      //...codes..
    }
}

// CHILD CLASS
public class Child extends Parent {
   // --- Fields ---
    // --- Methods --
    @Override
    public final void singing(){      // This is a programming error
      //...codes..                    // since this method is marked as final 
    }                                 // it cannot be overriden
}

Forcing Inheritance:

Use abstract keyword.  If you mark your class as abstract, that class can only be used in inheritance.  You cannot use it standalone such as creating an object from it. Note that abstract classes can contain normal methods and abstract methods.

// PARENT CLASS
public abstract class Fruit {
    String type;

    public abstract void showOrigin();   // abstract method 

    public void showFruitInfo(){         // normal method 
        System.out.println("This fruit is of type: " + type);
    }
}

// Programming Erorr!!
// Abstract class is for inheritance only,
// object creation is not allowed. 
Fruit favorite = new Fruit();  

If the abstract class contains abstract methods, then the child class must override and provide the method body for the abstract methods.  This is one way of forcing method override in the child class.

1
2
3
4
5
6
7
8
9
public class Apple extends Fruit {
    //-- Fields 
    //-- Methods 

    @Override    // <-- this is mandatory since showOrigin() is abstract method in Fruit 
    public void showOrigin(){
        System.out.println("This apple is from California");
    }
}



› Inheritance & Constructor

Please note that only the Fields and Methods are inherited.  The Constructor section of the class is not inherited.

If the superclass contains a unique constructor, you must call these constructors in subclass constructors. You can do this by using the super keyword.  Calling the superclass constructor inside the subclass constructor must be the first line of code in the Child class's constructor.

The super keyword in Java is used in subclasses to access superclass members (attributes, constructors, and methods).

Use of super keyword

  • To call methods of the super class that is overridden in the subclass.
  • To access attributes (fields) of the superclass if both superclass and subclass have attributes with the same name.
  • To explicitly call the superclass' constructor from the subclass constructor.
public class Parent {
    //--Fields 
    String name; 

    //--Constructor 
    public Parent(String n){
        name = n;
    }

    //--Methods: 
    public void showInfo(){
        System.out.println("Name: " + name);
    }

    public void drawLine(){
        System.out.println("=============");
    }
}
// SUB CLASS 
public class Child extends Parent {
    //--Fields--//
    int age;

    //--Constructor--//
    public Child(String n, int a){
        // calling Parent constructor to initialize 
        // name field, this must be the first line 
        super(n);    
        age = a;
    }

    //--Methods--// 
    @Override
    public void showInfo(){
        System.out.println("Name: " + super.name); // accessing Parent's field 
        System.out.println("Age : " + age);
        super.drawLine();                          // calling Parent's method 
    }
}
1
2
3
4
Child joe = new Child("Joe Pascal", 12);
joe.showInfo();    // prints: Name: Joe Pascal
                   // prints: Age : 12
                   // prints: =============



› Summary

Here is some key points I want you guys to remember about inheritance.

  • Inheritance uses the extends keyword in the form of ChildClass extends ParentClass
  • Child class overrides parent class's public methods.
  • All classes extend the Object class either directly or indirectly.
  • The super keyword allows access to the parent class fields and method in the child class.
  • The final keyword is used to prevent inheritance.
  • The abstract keyword is used to force inheritance.
  • Constructor is not inherited.