Inheritance

Learning Objectives

Lesson

Inheritance is fundamental to an object oriented programming language. Inheritance allows programmers to create classes that inherit the properties and functions/methods of a parent class. We often think of the inheritance relationship as a is a type of relationship, for example, car is a type of vehicle, triangle is a type of shape.

Inheritance supports code reusability by allowing shared properties and functions/methods to be defined in a base or super class and having sub classes inherit this state / behaviours and extend them if they wish.

We can even allow a sub class to override the behaviour it inherits from its super class - this is called polymorphism (meaning 'taking many forms').

Inheritance in an airport domain

Looking at our airport system we have 2 types of travellers - Passengers and Crew Members. Both share common properties such as a name, passport number, seat number and the bags they take when they travel. We can use inheritance to define a base class which holds these common features plus an addBag() function/method and allow the Passenger and Crew Member class to inherit these. Let's call this base class Traveller.

subclasses passenger and crew member inheriting from a super class traveller

A Traveller will have a name and a number of bags. The Person and Crew Member classes can inherit these properties by simply extending Traveller.

class Passenger extends Traveller {
    ....
}

Now when we create a new Passenger we will be able to call addBag() as this functionality has been inherited from the Traveller class.

Note that we need to take care when defining our constructor as we need to pass up to the super class, the properties which belong there. We do this using the super keyword.

class Passenger extends Person {

    constructor(name, passportNumber, seatNumber) {
        super(name, passportNumber);
        this.seatNumber = seatNumber;
    }
}
class Passenger extends Person {

    private seatNumber:string

    constructor(name:string, passportNumber:string, seatNumber:string) {
        super(name, passportNumber);
        this.seatNumber = seatNumber;
    }
}
public class Passenger extends Person {

    private String seatNumber;

    public Passenger(String name, String passportNumber, String seatNumber) {
        super(name, passportNumber);
        this.seatNumber = seatNumber;
    }
}

Our passengers might want behaviour specific to them like callAttendant(). In this case, we add the function/method to the Passenger subclass.

const Traveller = require('./Traveller')

class Passenger extends Traveller {
    callAttendant() {
        console.log('Excuse me, hey there!')
    }
}

Determining the type of a class

In your code you'll want to know what type an object is. For example, you might want to know, is this a Passenger or a Crew Member I am dealing with? You can use instanceof keyword to tell you.

test('is an instance of a Passenger', () => {
    const betty = new Passenger('Betty', 'ABC123', '1A')
    expect(betty instanceof Passenger).toBeTruthy()
})
@Test
public void isCorrectInstanceOf () {
    Passenger betty = new Passenger("Betty'", "ABC123", "1A");
    assertTrue(betty instanceof Passenger);
}

Assignment