Memra

Composition vs inheritance; extends & super

has-a vs is-a, base-class init via super(...), delegation, and when to prefer composition.

Two ways to reuse a class

There are two ways to build a new class out of an existing one:

- Composition (has-a): the new class *holds a reference* to the existing one as a field and forwards (delegates) work to it. A Car has an Engine. - Inheritance (is-a): the new class extends the existing one and *becomes a kind of* it, inheriting its members. A Truck is a Vehicle.

Java is single-inheritance: a class may extend exactly one superclass. Every class that does not name a superclass implicitly extends Object.

Worked example: compose an Engine, extend a Vehicle

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

class Car {                       // has-a: Car COMPOSES Engine
    private final Engine engine = new Engine();
    void drive() {
        engine.start();           // delegate to the held object
        System.out.println("Driving");
    }
}

Car does not expose Engine's methods; it *chooses* what to forward. You can swap the engine implementation later without changing Car's public surface. This loose coupling is why composition is the default choice.

super(...) drives base-class construction

With inheritance, the subclass must initialize the part of itself that belongs to the superclass. That happens through a super(...) call:

class Vehicle {
    private final int wheels;
    Vehicle(int wheels) { this.wheels = wheels; }
    int getWheels() { return wheels; }
}

class Truck extends Vehicle {     // is-a: Truck IS A Vehicle
    private final double tonnage;
    Truck(double tonnage) {
        super(6);                 // MUST be the first statement
        this.tonnage = tonnage;
    }
}

super(6) runs Vehicle's constructor before Truck initializes its own fields. It must be the first statement in the constructor. If you omit it, Java inserts an implicit super() (the no-arg superclass constructor) for you — and if the superclass has no no-arg constructor, that implicit call fails to compile. That is one of the most common surprises in inheritance.

When to prefer which

Prefer composition unless the subtype genuinely *is* a specialized form of the supertype and can stand in for it everywhere (the Liskov substitution test). Inheriting only to reuse a few methods couples you to the superclass's entire interface and its future changes — a fragile bargain.

NORMAL ~/memra/learn/comp-308/composition-vs-inheritance utf-8 LF