Understanding Inheritance in OOP
What is Inheritance?
Inheritance
Inheritance is a fundamental concept in object-oriented programming (OOP) that allows a class (subclass/child) to reuse and extend the attributes and methods of another class (superclass/parent).
It promotes code reusability, reduces duplication, and establishes a hierarchical relationship between classes.
Inheritance enables a hierarchical relationship between classes, promoting code reusability and reducing redundancy.
How Inheritance Works
- Superclass (Parent Class):
- Defines shared attributes and methods.
- Example: Vehicle has attributes like speed, capacity, and methods like move().
- Subclass (Child Class):
- Inherits attributes and methods from the parent.
- Can add its own specialized features.
- Example: Car adds numberOfDoors; Aeroplane adds fly().
- Consider a Vehicle superclass with attributes like fuelType and capacity.
- Subclasses like Car and Aeroplane inherit these attributes and add their own, such as electric for Car or commercial for Aeroplane.
Benefits of Inheritance
- Single Inheritance: One parent → one child.
- Multilevel Inheritance: A child acts as a parent for another child (e.g., Vehicle → Car → ElectricCar).
- Hierarchical Inheritance: Multiple children share the same parent.
- Multiple Inheritance: Supported in Python (via multiple parent classes) but not directly in Java (handled using interfaces).
When designing a class hierarchy, focus on identifying common attributes and behaviors that can be abstracted into a superclass.
Access Modifiers and Inheritance
- Public: Accessible everywhere.
- Protected: Accessible within the package (Java) or subclass (Java/Python).
- Private: Not inherited; accessible only inside the parent class.
- Default (Java): Package-level access.
Implementing Inheritance in Java and Python
Python:
class Vehicle:
def __init__(self):
self.type = "General Vehicle"
def move(self):
print("Vehicle is moving...")
class Aeroplane(Vehicle):
def fly(self):
print("Aeroplane is flying...")
# Testing inheritance
a = Aeroplane()
print(a.type) # inherited attribute
a.move() # inherited method
a.fly() # subclass methodJava:
class Vehicle {
String type = "General Vehicle";
void move() {
System.out.println("Vehicle is moving...");
}
}
class Aeroplane extends Vehicle {
void fly() {
System.out.println("Aeroplane is flying...");
}
}
public class TestInheritance {
public static void main(String[] args) {
Aeroplane a = new Aeroplane();
System.out.println(a.type); // inherited attribute
a.move(); // inherited method
a.fly(); // subclass method
}
}In both Java and Python, thesuperkeyword is used to call the constructor of the superclass, ensuring that inherited attributes are initialized correctly.
Access Modifiers and Inheritance
Understanding Access Modifiers
- Access modifiers control the visibility of class members (attributes and methods) in Java.
- Python uses naming conventions to achieve similar effects.
- Private: Accessible only within the class.
- Protected: Accessible within the class and its subclasses.
- Public: Accessible from anywhere.
- Default (Java only): Accessible within the same package.
- Students often assume that private members are accessible in subclasses.
- Remember, private members can only be accessed within the class they are declared in.
Impact on Inheritance
- Private Members: Not accessible in subclasses. Use public accessor methods to access them.
- Protected Members: Accessible in subclasses, promoting code reuse while maintaining encapsulation.
- Public Members: Fully accessible in subclasses and outside the class hierarchy.
- In the Vehicle class, attributes like fuelType are private.
- Subclasses access them through public methods like getFuelType().
Practical Applications of Inheritance
Code Reusability and Maintenance
- Reusability: Common code is stored in the superclass, reducing duplication.
- Maintenance: Changes in the superclass automatically apply to all subclasses, simplifying updates.
- Inheritance is a powerful tool, but it should be used judiciously.
- Overusing inheritance can lead to complex hierarchies that are difficult to manage.
- Using inheritance where composition is better (e.g., a Car has-an Engine, not is-an Engine).
- Forgetting that private members are not directly inherited.
- Overriding methods incorrectly (missing @Override in Java, incorrect method signature).
- Assuming multiple inheritance works the same across languages (Java uses interfaces, Python allows multiple parent classes).