【发布时间】:2011-05-20 10:41:52
【问题描述】:
一个月前我问过类似的问题:Inheritance though composition?
我从这篇文章中拿了一些例子:http://www.javaworld.com/javaworld/jw-11-1998/jw-11-techniques.html?page=1 然而,这一次是一个不同的问题。抱歉贴了很多代码,不过就是长,不难读。
class Fruit {
public int peel() {
System.out.println("Peeling is appealing.");
return 1;
}
}
class Apple extends Fruit {
}
class Example1 {
public static void main(String[] args) {
Apple apple = new Apple();
int pieces = apple.peel();
}
}
修改后就不行了:
class Peel {
private int peelCount;
public Peel(int peelCount) {
this.peelCount = peelCount;
}
public int getPeelCount() {
return peelCount;
}
}
修改 Fruit 类会导致编译错误代码。
class Peel {
private int peelCount;
public Peel(int peelCount) {
this.peelCount = peelCount;
}
public int getPeelCount() {
return peelCount;
}
}
class Fruit {
// Return a Peel object that
// results from the peeling activity.
public Peel peel() {
System.out.println("Peeling is appealing.");
return new Peel(1);
}
}
旧的实现已损坏。这个问题可以通过组合来解决:
class Peel {
private int peelCount;
public Peel(int peelCount) {
this.peelCount = peelCount;
}
public int getPeelCount() {
return peelCount;
}
}
class Fruit {
// Return int number of pieces of peel that
// resulted from the peeling activity.
public Peel peel() {
System.out.println("Peeling is appealing.");
return new Peel(1);
}
}
// Apple must be changed to accomodate
// the change to Fruit
class Apple {
private Fruit fruit = new Fruit();
public int peel() {
Peel peel = fruit.peel();
return peel.getPeelCount();
}
}
// This old implementation of Example2
// still works fine.
class Example1 {
public static void main(String[] args) {
Apple apple = new Apple();
int pieces = apple.peel();
}
}
随着构图的风格,苹果不再是-与水果的关系。它变成了一个has-a。 Fruit 中的方法作为继承委托给 Apple。我的问题出现了:
使用包装器方法从 Fruit 委托方法,这不是促进复制和粘贴,这是一种不好的做法吗?如果我们在 Fruit 中有大约 10-50 种方法,则为图像。如果有大约 50 个子类要继承,怎么可能通过组合来继承?
-
关于第一个例子,使用扩展继承,作者建议超类中的一次更改将破坏使用它的实现。但是,我想知道,为什么需要更改它? OO原则之一不是“关闭修改,打开扩展”吗?在作者所说的情况下,我仍然可以保留旧的超类实现并使其适应新的变化。像这样:
类水果{
// Return a Peel object that // results from the peeling activity. private Peel getPeel() { System.out.println("Peeling is appealing."); return new Peel(1); } public int peel(){ Peel peel = getPeel(); return peel.getPeelCount(); }}
向超类添加新方法以适应而不是更改或替换旧方法是否有问题,这会破坏程序结构?据我所知,通过这样做,我仍然可以实现与组合示例相同的事情,并且我不必制作很多包装方法来为每个子类委托超类的方法。
- 由于上述原因,我自己总结认为,只有当有多重继承时,或者当我需要共享不同且不属于一个类族的行为时,才使用组合更好。例如:
界面健谈{
public void talk();
}
Animal 类族可以实现 Talkative 接口以及 Person 类族。你觉得我的结论怎么样?
【问题讨论】:
标签: java design-patterns