Principles of Object Oriented Programming — Part Two: Inheritance — The Inquisitive Dev

The Inquisitive Dev
6 min readOct 6, 2020

This article is part of a series:

Part One: Encapsulation

Part Two: Inheritance

Part Three: Polymorphism

Part Four: Abstraction

Each week I am writing about a principle of object oriented programming. Last time I wrote about Encapsulation, wherein objects keep their data fields private whilst exposing a few public methods. This week I will talk about Inheritance.

This article was original published at:

Inheritance is a key principle of object oriented programming. It allows one class to acquire the fields and methods of another class. The class being inherited from is known as the super or parent class. The class doing the inheritance, is known as the sub or child class. Inheritance allows code to be written once and inherited by multiple child classes, thus reducing code duplication. Furthermore, code common to multiple objects can be changed once in the parent class, making the code more maintainable.

There are different types of inheritance:

  • Single — One class inheriting from another class
  • Multiple — One class inheriting from multiple classes (not supported in Java)
  • Multilevel — One class inherits from another class, which in turn, inherits from another class.
  • Hierarchical — multiple classes all inherit from one other class
  • Hybrid — a combination of single and multiple inheritance. A single base class is inherited from by two other classes, which in turn are both inherited from by one single class. (not supported in Java)

Inheritance in Java

In this article we will be using Java. In Java we can make use of single, multilevel and hybrid inheritance. To inherit from a class we add the extends keyword into the class signature followed by the name of the parent class.

Single Inheritance

public class Car { 
public void startEngine(){
System.out.println("Starting Engine");
}
}
public class Audi extends Car {
public void tailGate(){
System.out.println("Tailgating");
}
}
public class Driver {
public static void main(String args[]) {
Audi audiDriver = new Audi();
audiDriver.startEngine();
audiDriver.tailGate();
}
}

In the example above we have a parent class, Car. This class has a method called startEngine(). The Audi class inherits from the Car class using the extends keyword. It also has its own method called tailGate(). This makes the Audi class a child class of Car. As a result, the Audi class can make use of the startEngine() method, as well as its own tailGate() method.

In a scenario like the one above, where we have an ‘is a’ relationship between two objects, it is good practice to use inheritance. An Audi 'is a' type of Car. All types of Car will need a startEngine() method, so instead of declaring the same method in each child class, they all inherit it from their parent class. This avoids code duplication and enhances maintainability.

Multilevel Inheritance

public class Car { 
void startEngine(){
System.out.println("Starting Engine");
}
}
public class Audi extends Car {
void tailGate(){
System.out.println("Tailgating");
}
}
public class R8 extends Audi {
void breakSpeedLimit(){
System.out.println("Need for speed");
}
}
public class Driver {
public static void main(String args[]) {
R8 r8 = new R8();
r8.startEngine();
r8.tailGate();
r8.breakSpeedLimit();
}
}

In the example above we add a another class called R8 that inherits from Audi. The R8 child class will inherit all properties of Car and Audi.

Hierarchical Inheritance

public class Car { 
void startEngine(){
System.out.println("Starting Engine");
}
}
public class Audi extends Car {
void tailGate(){
System.out.println("Tailgating");
}
}
public class Bmw extends Car {
void soundHorn(){
System.out.println("Sounding Horn");
}
}
public class Driver {
public static void main(String args[]) {
Audi audiDriver = new Audi();
audiDriver.startEngine();
audiDriver.tailGate();
audiDriver.soundHorn(); //undefined

Bmw bmwDriver = new Bmw();
bmwDriver.startEngine();
bmwDriver.soundHorn();
bmwDriver.tailGate(); //undefined
}
}

The example above really shows the power of inheritance. When you have a one-to-many relationship between the parent class and the child class we can use hierarchical inheritance. This allows multiple child classes to inherit from a single parent class. We cut down on a lot of code repetition and increase the codes maintainability. Each child class can add its own properties, which won’t be available to other child classes that share the same parent class.

The super keyword

A child class method with the same name as a parent class method will overwrite it.

Child classes can make a call to super, which gives them access to all the parent class methods, even ones that have been overwritten.

public class Bicycle { 
public void printMethod() {
System.out.println("I'm a Bicycle");
}
}
public class MountainBike extends Bicycle {
// overrides printMethod in Bicycle
public void printMethod() {
super.printMethod();
System.out.println("I'm a Mountain bike");
}
}
public static void main(String[] args) {
MountainBike mb = new MountainBike();
mb.printMethod();
}
}

Above we define a parent class called Bicycle which has a method called printMethod(). The child class, MountainBike also has a printMethod() so this version of will overwrite the Bicycle version.

You’ll notice the MountainBike class adds a call to super.printMethod() which will call the parent classes method.

Compiling and executing the main method prints the following to the console:

I'm a Bicycle I'm a Mountain bike

Child class Constructors

You can use the super keyword to call the constructor of the parent class.

Below we have a parent class called Car.

public class Car {     public int numOfDoors; 
public boolean isConvertable;
public Car() {
//no arg constructor
};

public Car (int numOfDoors, boolean isConvertable) {
this.numOfDoors = numOfDoors;
this.isConvertable = isConvertable;
}
void startEngine(){
System.out.println("Starting Engine");
}

public void carSpec() {
System.out.println("Number of Doors: " + numOfDoors);
System.out.println("Is it convertable: " + isConvertable);
}
}

The Car class has a no argument constructor, as well as a constructor with arguments. It also has a couple of class methods, startEngine() and carSpec(). These class methods are common to all cars so it makes sense to have them in the parent class.

public class Audi extends Car { 
public String model;

public Audi(String model) {
super(4, true); this.model = model;
}
//overwrites Car classes startEngine method
void startEngine() {
System.out.println("Starting Audi " + model + " Engine");
super.startEngine();
super.carSpec();
}
}

The Audi class inherits from the Car class. In its constructor it sets its own class fields and makes a call to the Car classes constructor with the super keyword, passing the parameters 4 and true. When the Car constructor is called with these values they are passed into the Car classes fields numOfDoors and isConvertable respectively. These fields are then used in the Car classes carSpec() method to print to the console.

The Audi class overwrites the Car classes startEngine() method but makes a call to the Car classes methods using super.startEngine() and super.carSpec().

public class Driver { 
public static void main(String args[]) {
Audi audiDriver = new Audi("A1");
audiDriver.startEngine();
}
}

Running the Driver class would result in the following output:

Starting Audi A1 Engine Starting Engine Number of Doors: 4 Is it convertable: true

Little bit more…

If a child class constructor does not explicitly invoke a parent constructor using the super keyword, the Java compiler automatically inserts a call to the no-argument constructor of the parent class, super(). However, if the parent class does not have a no-argument constructor, you will get a compile-time error. The Object class, which all other object inherit from, does have such a constructor, so if Object is the only superclass, you'll be fine.

Sounding Off

So that’s the basics of inheritance in object oriented programming. There are other OOP languages but in this article we used Java for the examples. We talked about, single, multilevel and hierarchical inheritance. We then moved onto method overwriting in the child class and how the super keyword can be used to access the parent object.

Subscribe?

If you found this article useful I’d love you to become a subscriber to my blog. I will be dropping articles regularly on all things coding. Knowing I have people reading would mean the world. Head over to my site and hit the subscribe button. You will also find links to my social media channels so why don’t you say hi!

Thanks for reading

Ben

Originally published at https://theinquisitivedev.com on October 6, 2020.

--

--