Inheritance
Code reuse through parent-child relationships
Overview
Inheritance is a mechanism where a new class (child/subclass) derives properties and behaviors from an existing class (parent/superclass). It promotes code reuse and establishes an "is-a" relationship between classes.
While powerful, inheritance should be used carefully. Favor composition over inheritance when the relationship isn't truly "is-a".
Key Concepts
Parent/Superclass: Base class being inherited from
Child/Subclass: Class that inherits
extends keyword in Java
Method overriding: Child can modify parent behavior
super keyword: Access parent class members
Types: Single, Multilevel, Hierarchical (Java supports these)
Code Example
1// Parent class
2public class Vehicle {
3 protected String brand;
4 protected String model;
5 protected int year;
6
7 public Vehicle(String brand, String model, int year) {
8 this.brand = brand;
9 this.model = model;
10 this.year = year;
11 }
12
13 public void start() {
14 System.out.println("Vehicle is starting...");
15 }
16
17 public void stop() {
18 System.out.println("Vehicle is stopping...");
19 }
20
21 public void displayInfo() {
22 System.out.println(year + " " + brand + " " + model);
23 }
24}
25
26// Child class
27public class Car extends Vehicle {
28 private int numDoors;
29 private String fuelType;
30
31 public Car(String brand, String model, int year, int numDoors, String fuelType) {
32 super(brand, model, year); // Call parent constructor
33 this.numDoors = numDoors;
34 this.fuelType = fuelType;
35 }
36
37 // Method overriding
38 @Override
39 public void start() {
40 System.out.println("Car engine is starting... Vroom!");
41 }
42
43 // Child-specific method
44 public void openTrunk() {
45 System.out.println("Trunk is now open");
46 }
47
48 @Override
49 public void displayInfo() {
50 super.displayInfo(); // Call parent method
51 System.out.println("Doors: " + numDoors + ", Fuel: " + fuelType);
52 }
53}
54
55// Another child class
56public class Motorcycle extends Vehicle {
57 private boolean hasSidecar;
58
59 public Motorcycle(String brand, String model, int year, boolean hasSidecar) {
60 super(brand, model, year);
61 this.hasSidecar = hasSidecar;
62 }
63
64 @Override
65 public void start() {
66 System.out.println("Motorcycle engine roaring!");
67 }
68
69 public void wheelie() {
70 System.out.println("Doing a wheelie!");
71 }
72}
73
74// Usage
75public class Main {
76 public static void main(String[] args) {
77 Vehicle car = new Car("Toyota", "Camry", 2024, 4, "Hybrid");
78 Vehicle bike = new Motorcycle("Harley", "Sportster", 2024, false);
79
80 car.start(); // Car engine is starting... Vroom!
81 bike.start(); // Motorcycle engine roaring!
82
83 car.displayInfo(); // Shows car info with doors and fuel
84 }
85}Car and Motorcycle inherit from Vehicle but override methods to provide specific behavior. They can also add their own methods.
When to Use
When there is a genuine "is-a" relationship
To share common code among related classes
When subclasses need to extend or modify parent behavior
For creating class hierarchies
Advantages
- ✓
Code reuse - avoid duplication
- ✓
Establishes natural hierarchy
- ✓
Enables polymorphism
- ✓
Easier maintenance of shared code
Disadvantages
- ✗
Tight coupling between parent and child
- ✗
Changes in parent can break children
- ✗
Can lead to deep hierarchies (hard to understand)
- ✗
Java doesn't support multiple inheritance of classes
Best Practices
- 1.
Favor composition over inheritance when unsure
- 2.
Keep inheritance hierarchies shallow (max 2-3 levels)
- 3.
Use inheritance for "is-a", composition for "has-a"
- 4.
Don't inherit just to reuse code - use composition
- 5.
Follow Liskov Substitution Principle
💡 Interview Tips
Explain "is-a" vs "has-a" relationships
Discuss when to use inheritance vs composition
Know about method overriding vs overloading
Explain super keyword usage
Mention LSP (child should be substitutable for parent)