Bruce Eckel's Thinking in Java Contents | Prev | Next

Choosing composition

vs. inheritance

Both composition and inheritance allow you to place subobjects inside your new class. You might wonder about the difference between the two, and when to choose one over the other.

Composition is generally used when you want the features of an existing class inside your new class, but not its interface. That is, you embed an object so that you can use it to implement features of your new class, but the user of your new class sees the interface you’ve defined rather than the interface from the embedded object. For this effect, you embed private objects of existing classes inside your new class.

Sometimes it makes sense to allow the class user to directly access the composition of your new class; that is, to make the member objects public. The member objects use implementation hiding themselves, so this is a safe thing to do and when the user knows you’re assembling a bunch of parts, it makes the interface easier to understand. A car object is a good example:

//: Car.java
// Composition with public objects

class Engine {
  public void start() {}
  public void rev() {}
  public void stop() {}
}

class Wheel {
  public void inflate(int psi) {}
}

class Window {
  public void rollup() {}
  public void rolldown() {}
}

class Door {
  public Window window = new Window();
  public void open() {}
  public void close() {}
}

public class Car {
  public Engine engine = new Engine();
  public Wheel[] wheel = new Wheel[4];
  public Door left = new Door(),
       right = new Door(); // 2-door
  Car() {
    for(int i = 0; i < 4; i++)
      wheel[i] = new Wheel();
  }
  public static void main(String[] args) {
    Car car = new Car();
    car.left.window.rollup();
    car.wheel[0].inflate(72);
  }
} ///:~ 

Because the composition of a car is part of the analysis of the problem (and not simply part of the underlying design), making the members public assists the client programmer’s understanding of how to use the class and requires less code complexity for the creator of the class.

When you inherit, you take an existing class and make a special version of it. In general, this means that you’re taking a general-purpose class and specializing it for a particular need. With a little thought, you’ll see that it would make no sense to compose a car using a vehicle object – a car doesn’t contain a vehicle, it is a vehicle. The is-a relationship is expressed with inheritance, and the has-a relationship is expressed with composition.

Contents | Prev | Next