7️⃣

12.7 Inheritance

Before we discuss what inheritance is in code, let’s talk about what it means in real life. We often inherit our traits and behaviors from our parents through our genes or the way they raise us. People can also inherit belongings through wills. In programming, inheritance works the same way. A class (a subclass or child class) that inherits another class (a superclass or parent class) is able to use its methods and fields (assuming they aren’t private).

Inheritance is useful in programming because it describes an is-a relationship. For example, I could have a superclass called Instrument. The subclasses Guitar, Piano, and Flute could all inherit from Instrument because Guitars, Pianos, and Flutes are Instruments.

Inheritance which allows for greater abstraction because the fields and methods that are common to all instruments can be defined in the Instrument class, while the fields and methods specific to Guitars, Pianos, and Flutes are only defined in their respective classes.

For instance, it doesn’t make sense to have a field called numberOfStrings in the Flute class, but it does make sense for it to be in the Guitar class. Similarly, since both Guitars and Flutes can be played, it would make sense to have a play() method in the Instrument class since all instruments can be played.

So how do you actually express inheritance using Java syntax? You need to use the extends keyword to signify that the class inherits from a superclass. For example

class Guitar extends Instrument {
		// class body
}
View this code on GitHub

💡

Note: A subclass can only extend 1 superclass, so design your classes carefully!

Super Keyword

Recall that the this keyword is used to refer to the current object. There’s also another handy keyword called super which allows you to refer to the superclass. Specifically, you can use it to call superclass methods (including the superclass constructor) and access superclass fields.

Analyze the following code, for example. Pay attention to the highlighted parts.

public class TestInstrument {

    public static void main(String[] args) {
        // construct a new Guitar object
        Guitar taylorGuitar = new Guitar("acoustic", "steel");

        // print the Guitar object
        System.out.println(taylorGuitar);

        // prints "Playing instrument" 6 times
        taylorGuitar.strum();
    }
}

class Instrument {

    private String name;

    public Instrument() {
        name = "";
    }

    public Instrument(String name) {
        this.name = name;
    }

    public void play() {
        System.out.println("Playing instrument");
    }

    @Override
    public String toString() {
        return "Instrument, name: " + name;
    }
}

class Guitar extends Instrument {

    private String type;
    private String stringType;

    public Guitar() {
        super("guitar");
        type = "acoustic";
        stringType = "steel";
    }

    public Guitar(String type, String stringType) {
        super("guitar");
        this.type = type;
        this.stringType = stringType;
    }

    public void strum() {
        for (int i = 0; i < 6; i++) {
            super.play(); // use super.methodName() to call a superclass method
        }
    }

    @Override
    public String toString() {
        return stringType + "-string " + type + " guitar";
    }
}
View this code on GitHub

💡

Note: Getters and setters were omitted from the implementation above for simplicity.

As you may have noticed, to call a superclass constructor, you use super(list of parameters). The default superclass constructor (super()) is called implicitly (by default) for any subclass’s constructor. However, if you want to use a superclass constructor with 1 or more arguments, you must do so explicitly (you have to write it out in code).

You also may have noticed that to access a superclass’s methods or fields, you simply use dot notation with the super keyword. For example, in the strum() method in the Guitar class, super.play() is called 6 times.

Practice:

Piano

Create the Piano class (which inherits the Instrument class) such that when you call the playTriad() method, it calls the play() method from the Instrument class 3 times.

Also make sure to call the 1-argument superclass constructor in both the default and 2-argument Piano constructors. (The name of the instrument is "piano".)

UML diagram for the Piano class:

Piano

NameTags
fields
- hammerWeight: double
- backPostMaterial: String
Methods
+ Piano()
+ Piano(hammerWeight: double, backPostMaterial: String
+ playTriad(): void
+ toString(): String

💡

Note: For the toString() method, you can do whatever you want as long as it displays the Piano object well.

Previous Section

Next Section

⚖️

Copyright © 2021 Code 4 Tomorrow. All rights reserved. The code in this course is licensed under the MIT License. If you would like to use content from any of our courses, you must obtain our explicit written permission and provide credit. Please contact classes@code4tomorrow.org for inquiries.