Inheritance
Inheritance
An OOP principle where one class (the subclass) can reuse and extend the attributes and methods of another class (the superclass).
The Parent-Child Relationship
- Parent Class (Superclass):
- Contains common data and actions that can be shared with multiple child classes.
- Serves as a blueprint for its subclasses.
- Child Class (Subclass):
- Inherits data and actions from the parent class.
- Can add new features or override existing ones to provide specialised behaviour.
- Think of inheritance like a family tree.
- The parent class is the ancestor, and child classes are descendants that inherit traits but can also have unique characteristics.
- Consider a Person class with attributes like name and age, and a method walk().
- A Student class can inherit from Person, gaining these attributes and methods while adding its own, such as study().
In Java, inheritance is defined via the keyword extends.
public class Dog extends Animal {
...
}Here,Ā DogĀ is a subclass andĀ AnimalĀ is a superclass.
How Inheritance Works
- Data inheritance:
- Child classes inherit attributes from the parent class.
- These attributes can be used or overridden as needed.
- Action inheritance:
- Child classes inherit methods from the parent class.
- Methods can be overridden to provide specialised behaviour.
- When designing a class hierarchy, start by identifying common features that can be placed in a parent class.
- This promotes code reuse and simplifies maintenance.
- A Bird class might have a fly() method.
- AĀ PenguinĀ class canĀ overrideĀ thisĀ methodĀ toĀ reflectĀ thatĀ penguins cannot fly, while stillĀ inheritingĀ otherĀ characteristicsĀ likeĀ eat() orĀ swim().
public class Bird { // parent class
public void fly() {
System.out.println("This bird can fly.");
}
public void eat() {
System.out.println("The bird is eating.");
}
public void swim() {
System.out.println("Some birds can swim.");
}
}
public class Penguin extends Bird { // child class
@Override
public void fly() { // overriding the fly() method
System.out.println("Penguins cannot fly.");
}
public static void main(String[] args) {
Bird genericBird = new Bird();
genericBird.fly(); // output: This bird can fly.
genericBird.eat(); // output: The bird is eating.
Penguin penguin = new Penguin();
penguin.fly(); // output: Penguins cannot fly.
penguin.eat(); // output: The bird is eating.
penguin.swim(); // output: Some birds can swim.
}
}@Override in Java:
- @Override is an annotation that tells the compiler that a method in a subclass is intended to replace (override) a method in its parent class.
- It ensures compile-time checking, so if you accidentally mismatch the method name or parameters, the compiler will give an error.
- While it is not necessary, using @Override improves code readability and makes it clear that the subclass is providing a specialised version of a parent method.
Advantages of Inheritance
Code reusability:
- Inheritance allows child classes to reuse the data and actions of a parent class.
- This eliminates the need to rewrite code, reducing duplication and errors.
- Consider a Vehicle class with methods like start() and stop().
- AĀ Car class canĀ inheritĀ theseĀ methodsĀ withoutĀ rewritingĀ them,Ā focusingĀ only onĀ car-specificĀ features.
public class Vehicle { // parent class
public void start() {
System.out.println("Vehicle is starting...");
}
public void stop() {
System.out.println("Vehicle is stopping...");
}
}
public class Car extends Vehicle { // child class
public void honk() { // car-specific feature
System.out.println("Car horn: Beep Beep!");
}
public static void main(String[] args) {
Car myCar = new Car();
// testing inherited methods from Vehicle
myCar.start();
myCar.stop();
// testing car-specific method
myCar.honk();
}
}
Extensibility:
- Inheritance enables child classes to extend the functionality of a parent class.
- Child classes can add new methods or override existing ones to suit their specific needs.
Reduced maintenance overheads:
- Changes made to a parent class automatically propagate to all child classes.
- This centralises updates, reducing the effort required to maintain the codebase.
When updating a method in a parent class, always test its impact on all child classes to ensure compatibility.
Information hiding:
- Parent classes can control which data and methods are accessible to child classes.
- This ensures that sensitive or irrelevant details are kept hidden, promoting a cleaner and more secure design.
Information hiding is a key principle of encapsulation, which works hand-in-hand with inheritance to create robust object-oriented systems.
Hierarchical organisation:
- Inheritance naturally organises code into a hierarchy, reflecting real-world relationships.
- This structure makes it easier to understand and navigate the codebase.
Disadvantages of Inheritance
- Tight coupling:
- Child classes are tightly coupled to their parent classes, making changes to the parent class potentially disruptive.
- Single inheritance:
- Most programming languages, like Java, support only single inheritance, where a class can inherit from only one parent.
- This limitation is addressed by interfaces or mixins.
The problem of multiple inheritance is also referred to as theĀ diamond problem.
Diamond problem explained
- Avoid using inheritance solely for code reuse.
- If two classes share functionality but are not conceptually related, consider using composition instead.
Inheritance in UML Diagrams
UML (Unified Modelling Language) diagrams visually represent inheritance relationships using an open arrow pointing from the child class to the parent class.
- How does inheritance promote code reusability and extensibility?
- Can you think of a scenario where overriding a parent method would be necessary?
- How does inheritance contribute to reduced maintenance overheads?