choosing composition vs inheritance

1. Using composition when you want the functionality of an existing class inside your new class, but not its interface. That is, embed a (usually private) object to implement features in your new class. The user of your new class sees the interface you've defined for new class rather than the interface from the embedded object.

Sometimes it makes sense to allow the class user to directly access the composition of your new class. For this, make the member objects public (you can think of this as a kind of "semi-delegation"). The member objects use implementaion hiding themselves, so this is safe. 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:

// reuse/Car.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// 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

  public 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);
  }
}

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. However, keep in mind this is a special case. In general, make fields private .

2. When you inherit, you take an existing class and make a special version of it. This usually means taking a general-purpose class and specializing it for a particular need. With a little thought, you’ll see 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.

Although it's possible to create protetected fields, the best approach is to leave the fields private and always preserve your right to change the underlying implementation.

One of the clearest ways to determine whether to use composition or inheritance is to ask whether you'll ever upcast from your new class to the base class. If you must upcast, inheritance is necessary, buf if you don't upcast, look closely at whether you need inheritance.

A general guideline is “Use inheritance to express differences in behavior, and fields to express variations in state.” In the following example, both are used; two different classes are inherited to express the difference in the act() method, and Stage uses composition to allow its state to be changed. Here, that change in state happens to produce a change in behavior.

// polymorphism/Transmogrify.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Dynamically changing the behavior of an object
// via composition (the "State" design pattern)

class Actor {
  public void act() {}
}

class HappyActor extends Actor {
  @Override
  public void act() {
    System.out.println("HappyActor");
  }
}

class SadActor extends Actor {
  @Override
  public void act() {
    System.out.println("SadActor");
  }
}

class Stage {
  private Actor actor = new HappyActor();

  public void change() {
    actor = new SadActor();
  }

  public void performPlay() {
    actor.act();
  }
}

public class Transmogrify {
  public static void main(String[] args) {
    Stage stage = new Stage();
    stage.performPlay();
    stage.change();
    stage.performPlay();
  }
}
/* Output:
HappyActor
SadActor
*/

references:

1. On Java 8 - Bruce Eckel

2. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/reuse/Car.java

3. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/polymorphism/Transmogrify.java

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值