Composition vs Inheritance in Java

1. Introduction

In Java, composition and inheritance are two programming techniques that model the relationship between two classes. Inheritance is used to express an "is-a" relationship, indicating that one class is a specialized version of another. Composition, on the other hand, expresses a "has-a" relationship, indicating that one class contains an instance of another class as a part of its state.

2. Key Points

1. Inheritance extends a class using the extends keyword, creating a subclass that inherits methods and variables from the parent class.

2. Composition involves creating classes that contain instances of other classes within them.

3. Inheritance promotes code reusability but can lead to fragile code due to tight coupling.

4. Composition promotes code flexibility and reusability without the fragility of inheritance.

3. Differences

Inheritance Composition
Establishes an "is-a" relationship. Establishes a "has-a" relationship.
Tightly couples the subclass to the parent class. Loosely couples the classes, making changes more manageable.
Subclass inherits all accessible members and methods. Control over which methods and members can be accessed by containing class.

4. Example


// Example of Inheritance
class Vehicle {
    void start() {
        System.out.println("Vehicle started");
    }
}

class Car extends Vehicle {
    void openTrunk() {
        System.out.println("Trunk opened");
    }
}

// Example of Composition
class Engine {
    void start() {
        System.out.println("Engine started");
    }
}

class CarWithComposition {
    private Engine engine;

    CarWithComposition() {
        engine = new Engine();
    }

    void startCar() {
        engine.start();
        System.out.println("Car started");
    }
}

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.start(); // Inherited method
        car.openTrunk(); // Class method

        CarWithComposition compCar = new CarWithComposition();
        compCar.startCar(); // Composed method
    }
}

Output:

Vehicle started
Trunk opened
Engine started
Car started

Explanation:

1. The Car class inherits from Vehicle, demonstrating an "is-a" relationship. The car "is-a" vehicle.

2. The CarWithComposition class has an Engine, demonstrating a "has-a" relationship. The car "has-an" engine.

3. The Car class inherits the start method from Vehicle, while the CarWithComposition class can only start its Engine through its own startCar method.

4. CarWithComposition encapsulates the start behavior, and this encapsulation allows more control over the start process.

5. When to use?

- Use inheritance when classes are in a clear "is-a" relationship, and you want to reuse code from the base class.

- Use composition to create more flexible designs that don't break easily with changes to the base class or when the "has-a" relationship makes more sense for the model.

Comments