Class hierarchy
Inheritance connects a specific subclass to a more general superclass.
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.
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.
- 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
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.
Listing the members of myCar
A program creates an object named myCar of type Car. Which members can myCar use?
- 1Identify the class of the object
myCaris a Car object. Car extends Vehicle, so Car is a subclass of Vehicle. - 2Collect the members declared in Car
Car declares
numberOfDoors, somyCar.numberOfDoors is a valid reference. - 3Collect the members inherited from Vehicle
Because Car extends Vehicle, the car also has
registrationNumber, owner, andtransferOwnership()from Vehicle. SomyCar.registrationNumber,myCar.owner, andmyCar.transferOwnership()all exist. - 4Combine the two lists
The full set of members of
myCaris the inherited Vehicle members plus the Car membernumberOfDoors.
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?
Reveal 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.
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.
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 likeBelieving a Truck object has only numberOfAxles and not registrationNumber.
Why it failsA subclass inherits all the fields and methods of its parent class and also adds its own members.
Do this insteadBuild 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 likeUsing a Vehicle-typed variable to read numberOfDoors from a Car object.
Why it failsThe member access is checked against the class the reference is read through. Vehicle does not declare
numberOfDoors.Do this insteadRead 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 failsEach specific class is connected to a general class by inheritance, so shared structure is declared once at the parent level.
Practice: Tracing Member Access
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, andtransferOwnership.
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(), andnumberOfAxles. - 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.