Unit 3 · OOP Concepts

3.5.2Hierarchies and types of inheritance

Classes form a tree called a class hierarchy. The most general class is at the top.

VehicleCarBikeSedanSUVmore general ↑more specialised ↓
A class hierarchy: general classes at the top, specialised classes below

Types of inheritance:

TypeDescriptionJava
SingleOne subclass has one superclass (Dog extends Animal)Supported
MultilevelA chain: Animal, then Dog, then PuppySupported
HierarchicalSeveral subclasses share one superclass (Car and Bike extend Vehicle)Supported
MultipleOne subclass has two or more superclassesNot through classes; achieved through interfaces. C++ and Python allow it directly
SingleMultilevelHierarchicalMultipleAnimalDogAnimalDogPuppyVehicleCarBikeABCJava: yesJava: yesJava: yesclasses: nointerfaces: yes
Types of inheritance. Java allows multiple inheritance only through interfaces

Every Java class ultimately inherits from java.lang.Object.

Generalisation and specialisation

Moving up a hierarchy is generalisation: Dog and Cat have things in common, so you collect those into a more general class, Animal. Moving down is specialisation: a Puppy is a more specific kind of Dog. A good design puts each attribute and method at the highest level where it applies to every class below it. name and eat() belong in Animal, because every animal has them, but bark() belongs in Dog.

How to design a hierarchy

  1. List the classes you need and the attributes and methods of each.
  2. Look for attributes and methods that several classes share. Move them up into a superclass.
  3. Check every link with the is-a sentence. "A Manager is an Employee": yes. "A Department is an Employee": no.
  4. Keep it shallow. Two or three levels is usually enough; very deep hierarchies are hard to understand and to change.

Example: a hierarchy in code

Java
class Vehicle {
    protected String regNo;
    Vehicle(String regNo) { this.regNo = regNo; }
    void start() { System.out.println(regNo + " started"); }
}

class Car extends Vehicle {                  // hierarchical: Car and Bike
    Car(String regNo) { super(regNo); }      // both extend Vehicle
}

class Bike extends Vehicle {
    Bike(String regNo) { super(regNo); }
}

class SportsCar extends Car {                // multilevel: Vehicle -> Car -> SportsCar
    SportsCar(String regNo) { super(regNo); }
    void turbo() { System.out.println(regNo + " turbo on"); }
}

A SportsCar has regNo and start() from Vehicle and turbo() from itself.

The Object class

If a class does not say extends, Java makes it extend java.lang.Object automatically. So every class inherits a few useful methods, which it can override:

MethodWhat it does by defaultUsually overridden to ...
toString()Returns the class name and a code, such as Dog@1b6d3586return readable text such as "Dog: Rex"
equals(Object o)Same as ==: true only for the very same objectcompare the attribute values
hashCode()Returns a number based on the object's identitymatch equals() (needed by HashMap and HashSet)
getClass()Returns the object's actual class at run time(final, cannot be overridden)

Remember

  • Put shared members as high in the hierarchy as they apply to every class below.
  • Check each link with the is-a sentence and keep hierarchies shallow.
  • Every class inherits from Object, directly or indirectly.