Discuss the principle of "composition over inheritance". Provide an example where this principle should be applied in Java application design.

The principle of "Composition over Inheritance" recommends building classes by combining objects of other classes rather than inheriting behavior from parent classes whenever possible. Composition provides greater flexibility, lower coupling, and easier maintenance, making applications more adaptable to future changes.

Key Points: • Composition represents a "has-a" relationship, while inheritance represents an "is-a" relationship. • Composition promotes loose coupling because components can be replaced or modified independently. • Inheritance creates a strong dependency between parent and child classes. • Composition allows behavior to be changed at runtime by using different object implementations. • Modern frameworks such as Spring heavily rely on composition and dependency injection.

Example: A Car is not an Engine, but a Car has an Engine. Therefore, composition is more appropriate than inheritance.

Using inheritance:

class Engine {
}

class Car extends Engine {
}

This design is incorrect because a Car is not a type of Engine.

Using composition:

class Engine {

    void start() {
        System.out.println("Engine Started");
    }
}

class Car {

    private Engine engine;

    public Car(Engine engine) {
        this.engine = engine;
    }

    void startCar() {
        engine.start();
    }
}

In this design, the Car class uses an Engine object rather than inheriting from it, creating a more flexible and maintainable solution.

Real-World Scenario: Consider a notification system where notifications can be sent through Email, SMS, or WhatsApp.

Instead of:

class EmailNotification extends Notification
class SmsNotification extends Notification
class WhatsAppNotification extends Notification

A better approach is:

class Notification {
    private MessageService service;
}

Here, different MessageService implementations can be injected at runtime, making the application easier to extend and maintain.

Benefits of Composition Over Inheritance:

• Loose coupling • Better flexibility • Easier testing • Improved maintainability • Runtime behavior changes • Better support for dependency injection

Interview Tip: A concise interview answer is:

"Composition over inheritance means preferring object composition instead of class inheritance for code reuse. Composition creates a 'has-a' relationship, provides loose coupling, and offers greater flexibility. For example, a Car should contain an Engine object rather than inherit from the Engine class."