Concepts / Class hierarchy

Class hierarchy

Inheritance connects a specific subclass to a more general superclass.

  • Programming

A Program That Tracks Vehicles

Imagine a program that has to deal with motor vehicles, including cars, trucks, and motorcycles. A Department of Motor Vehicles might use a program like this to keep track of registrations. Every vehicle has a registration number and an owner, but each type of vehicle also has details that belong only to it. A car has a number of doors, a truck has a number of axles, and a motorcycle may or may not have a sidecar.

A program could treat each vehicle type as an unrelated thing, but that would repeat the shared parts in every type. The alternative is a class hierarchy. The program uses one general class named Vehicle to represent what all vehicles have in common, and separate, more specific classes for Car, Truck, and Motorcycle. The specific classes are connected to the general class by inheritance. This lesson traces how that connection works, which members each object ends up with, and where a member reference breaks.

Definition

Inheritance connects a specific subclass to a more general superclass. A class hierarchy is the arrangement that results: subclasses are connected to a parent class, which in this example is Vehicle with Car, Truck, and Motorcycle beneath it.

Sorting Vehicles into Levels

In the vehicle program, Vehicle sits at the top of the hierarchy as the superclass. Car, Truck, and Motorcycle sit one level below it as subclasses. Each subclass is declared with the word extends, which is what links it to its parent. The source gives these declarations in a Java-style notation, shown below as a sketch of the declarations described in the source. Only the member declarations are shown, not method bodies.

java
Notes on the code
  • Vehicle is the general superclass: it declares the members every vehicle shares
  • extends links each subclass to Vehicle
  • Each subclass adds one member that belongs only to its own type
VehiclesuperclassCaradds numberOfDoorsTruckadds numberOfAxlesMotorcycleadds hasSidecarparent ofparent ofparent of
Which class is the general superclass, which classes are specific subclasses, and how do the levels connect? Vehicle sits at the top, and each subclass is one level below it.

Read the diagram from the top down. Vehicle is the general class, holding the structure that all vehicles share. Each box below it is a more specific class, and each one adds a single member of its own. The hierarchy therefore states a common property once, at the broadest level, and records each difference at the narrower level where it applies. The source describes this as organizing related classes by common properties instead of treating every class as unrelated.

What a Car Object Contains

A subclass inherits all the fields and methods of its parent class, and also adds its own members. So an object created from Truck does not contain only the members written inside Truck. It also contains the members declared in Vehicle. Following the declarations above, the members come from two places. The inherited members come from Vehicle: registrationNumber, owner, and transferOwnership(). The member declared in Truck itself is numberOfAxles.

Truck objectregistrationNumberint fieldownerPerson fieldtransferOwnership()method taking a PersonnumberOfAxlesint fieldhashashashas
When a Truck object is created, which fields and methods come from Vehicle and which are declared in Truck itself?
Worked example

Listing the members of myCar

A program creates an object named myCar of type Car. Which members can myCar use?

  1. 1
    Identify the class of the object

    myCar is a Car object. Car extends Vehicle, so Car is a subclass of Vehicle.

  2. 2
    Collect the members declared in Car

    Car declares numberOfDoors, so myCar.numberOfDoors is a valid reference.

  3. 3
    Collect the members inherited from Vehicle

    Because Car extends Vehicle, the car also has registrationNumber, owner, and transferOwnership() from Vehicle. So myCar.registrationNumber, myCar.owner, and myCar.transferOwnership() all exist.

  4. 4
    Combine the two lists

    The full set of members of myCar is the inherited Vehicle members plus the Car member numberOfDoors.

Result

myCar can use registrationNumber, owner, transferOwnership(), and numberOfDoors.

Reading Members Through a Reference

A member reference, such as myCar.numberOfDoors, asks the program to read a member through an object. The reference succeeds only when the member exists in the class the reference is read through. The inheritance relationship flows downward in this example. Vehicle does not declare numberOfDoors, numberOfAxles, or hasSidecar, because those belong to the subclasses. A reference that depends on a subclass-only member therefore cannot be satisfied by a plain Vehicle reference.

What do you think happens?

A variable declared as Vehicle refers to a Truck object. Can the reference v.numberOfAxles read the numberOfAxles field?

  • Yes, because the object is a Truck

  • No, because numberOfAxles is not declared in Vehicle

Reveal answer
Answer:

No. The reference is read through the Vehicle class, and Vehicle does not declare numberOfAxles, so the member access fails at that point.

Even though the object really is a Truck, the reference only offers the members of the class it is read through. numberOfAxles is declared in Truck, a subclass of Vehicle, so a Vehicle-typed reference cannot provide it. The object's true class does not extend what the reference is allowed to see.

Vehicle referenceTruck objectregistrationNumberdeclared in VehiclenumberOfAxlesdeclared only in Truckpoints toread succeedsread fails
If a Vehicle-typed reference points to a Truck object, which members can be accessed through that reference, and at what point does an access to a Truck-only member fail?

The diagram shows the failure point. The reference points to a real Truck object, but the reference is read through Vehicle. The field registrationNumber is declared in Vehicle, so reading it through the Vehicle reference succeeds. The field numberOfAxles is declared only in Truck, so the access fails at the moment the reference is checked against the Vehicle declarations. The source describes this as the place to start when debugging, because it is where the result diverges from what you expected.

Reusing, Extending, and Overriding Inherited Behavior

Inheritance is not limited to copying a class unchanged. A subclass can use what it inherits, add to it, or change part of it. The source names three options: a subclass can reuse inherited properties, add new properties, or override an inherited response. Adding a member is what Car, Truck, and Motorcycle do with numberOfDoors, numberOfAxles, and hasSidecar. Overriding means defining a different response to a message the subclass has inherited.

Key point

Reuse means the subclass keeps an inherited member as it is. Extension means the subclass adds a member the parent does not have. Overriding means the subclass replaces the inherited response with its own. In each case the subclass starts from the parent class, which is why it is a controlled adaptation rather than a fresh, unrelated class.

This is also why inheritance supports software reuse. Lines, rectangles, ovals, polygons, and curves in a drawing program need separate classes, because they describe different kinds of shapes. They still share the fact that each is something the program can draw. A shared parent class records that common identity once, and each subclass records only what makes it different. When an existing class needs only small adaptations, a subclass can make those adaptations without rewriting the shared structure.

Mistakes with Class Hierarchies

  • Common mistake

    Assuming a subclass object has only the members declared in the subclass

    What it looks like

    Believing a Truck object has only numberOfAxles and not registrationNumber.

    Why it fails

    A subclass inherits all the fields and methods of its parent class and also adds its own members.

    Do this instead

    Build the member list in two parts: the inherited members from the parent, plus the members declared in the subclass.

  • Common mistake

    Reading a subclass-only member through a parent-class reference

    What it looks like

    Using a Vehicle-typed variable to read numberOfDoors from a Car object.

    Why it fails

    The member access is checked against the class the reference is read through. Vehicle does not declare numberOfDoors.

    Do this instead

    Read the member through a reference of the subclass type, or check that the member is declared in the class the reference uses.

  • Common mistake

    Treating the subclass and parent as unrelated classes

    Why it fails

    Each specific class is connected to a general class by inheritance, so shared structure is declared once at the parent level.

Practice: Tracing Member Access

MEDIUM

Using the Vehicle, Car, Truck, and Motorcycle declarations from this lesson, decide for each expression whether it is valid. Expression 1: myCar.numberOfDoors. Expression 2: myCar.owner. Expression 3: a Vehicle-typed reference v holding a Truck, read as v.numberOfAxles. Expression 4: a Motorcycle object m, read as m.transferOwnership(). For each one, name the class whose declarations make it valid or invalid.

Hints
  • Ask first which class declares the member, then whether that class is the one the reference is read through.
  • A subclass object inherits every member of its parent class.
  • Vehicle declares registrationNumber, owner, and transferOwnership.

Key Takeaways

  • Inheritance connects a specific subclass to a more general superclass, and a class hierarchy arranges those connections into levels, with Vehicle above Car, Truck, and Motorcycle.
  • A subclass object has the members inherited from its parent class plus the members it declares itself, so a Truck has registrationNumber, owner, transferOwnership(), and numberOfAxles.
  • A subclass can reuse inherited members, add new ones, or override an inherited response, which lets it adapt a parent class rather than start from scratch.
  • A member reference is valid only when the member is declared in the class the reference is read through, so a Vehicle-typed reference cannot read a Truck-only member such as numberOfAxles.