Classes form a tree called a class hierarchy. The most general class is at the top.
Types of inheritance:
| Type | Description | Java |
|---|---|---|
| Single | One subclass has one superclass (Dog extends Animal) | Supported |
| Multilevel | A chain: Animal, then Dog, then Puppy | Supported |
| Hierarchical | Several subclasses share one superclass (Car and Bike extend Vehicle) | Supported |
| Multiple | One subclass has two or more superclasses | Not through classes; achieved through interfaces. C++ and Python allow it directly |
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
- List the classes you need and the attributes and methods of each.
- Look for attributes and methods that several classes share. Move them up into a superclass.
- Check every link with the is-a sentence. "A Manager is an Employee": yes. "A Department is an Employee": no.
- 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
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:
| Method | What it does by default | Usually overridden to ... |
|---|---|---|
toString() | Returns the class name and a code, such as Dog@1b6d3586 | return readable text such as "Dog: Rex" |
equals(Object o) | Same as ==: true only for the very same object | compare the attribute values |
hashCode() | Returns a number based on the object's identity | match 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.