我听到(并在这个网站上读到)很多关于“偏好组合胜过继承”的信息。
但是什么是合成?我从 Person : Mammal : Animal 的角度理解继承,但我在任何地方都看不到 Compostion 的定义。有人可以填写吗?
我听到(并在这个网站上读到)很多关于“偏好组合胜过继承”的信息。
但是什么是合成?我从 Person : Mammal : Animal 的角度理解继承,但我在任何地方都看不到 Compostion 的定义。有人可以填写吗?
组合是指将简单的类型组合成更复杂的类型。在您的示例中,组合可能是:
Animal:
Skin animalSkin
Organs animalOrgans
Mammal::Animal:
Hair/fur mammalFur
warm-blooded-based_cirulation_system heartAndStuff
Person::Mammal:
string firstName
string lastName
如果你想完全组合(并摆脱所有继承),它看起来像这样:
Animal:
Skin animalSkin
Organs animalOrgans
Mammal:
private Animal _animalRef
Hair/fur mammalFur
warm-blooded-based_cirulation_system heartAndStuff
Person:
private Mammal _mammalRef
string firstName
string lastName
这种方法的优点是类型Mammal
和Person
不必符合其先前父级的接口。这可能是一件好事,因为有时对超类的更改会对子类产生严重影响。他们仍然可以通过这些类的私有实例访问这些类的属性和行为,如果他们想公开这些以前的超类行为,他们可以简单地将它们包装在一个公共方法中。
我在这里找到了一个很好的例子:http ://www.artima.com/designtechniques/compoinh.html
组合只是构成整体的部分。汽车有轮子、发动机和座椅。继承是一种“是”的关系。组合是一种“具有”关系。
可以通过三种方式为类赋予行为。您可以将该行为写入类中;您可以从具有所需行为的类继承;或者您可以将具有所需行为的类作为字段或成员变量合并到您的类中。最后两种代表代码重用的形式,最后一种——组合——通常是首选。它实际上并没有为您的类提供所需的行为 - 您仍然需要在字段上调用该方法 - 但它对您的类设计的约束更少,并且更容易测试和调试代码。继承有它的位置,但组合应该是首选。
class Engine
{
}
class Automobile
{
}
class Car extends Automobile // car "is a" automobile //inheritance here
{
Engine engine; // car "has a" engine //composition here
}
组合- 对象的功能由不同类的集合组成。在实践中,这意味着持有一个指向另一个工作被推迟的类的指针。
继承- 对象的功能由它自己的功能加上其父类的功能组成。
至于为什么组合优先于继承,请看一下圆椭圆问题。
组合的一个例子是你在另一个类中有一个类的实例,而不是从它继承
这个页面有一篇很好的文章解释了为什么人们说“喜欢组合而不是继承”,并举例说明了原因。
作品
仅仅意味着使用引用其他对象的实例变量。
1-通过继承编码
class Fruit {
// Return int number of pieces of peel that
// resulted from the peeling activity.
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();
}
}
当你Example1 application
运行peel()
. 但是,如果在将来的某个时候,您希望将 的返回值更改为peel()
Peel 类型,您将破坏Example1
. 即使 Example1 直接使用 Apple 并且从未明确提及 Fruit,您对 Fruit 的更改也会破坏 Example1 的代码。欲了解更多信息,请参考以下内容:
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);
}
}
// Apple still compiles and works fine
class Apple extends Fruit {
}
// This old implementation of Example1
// is broken and won't compile.
class Example1 {
public static void main(String[] args) {
Apple apple = new Apple();
int pieces = apple.peel();
}
}
2-通过组合编写代码组合
提供了一种Apple
复用Fruit's
实现的替代方法peel()
。代替扩展Fruit
,Apple
可以持有对Fruit
实例的引用并定义自己的peel()
方法,该方法只是peel()
在 Fruit 上调用。这是代码:
class Fruit {
// Return int number of pieces of peel that
// resulted from the peeling activity.
public int peel() {
System.out.println("Peeling is appealing.");
return 1;
}
}
class Apple {
private Fruit fruit = new Fruit();
public int peel() {
return fruit.peel();
}
}
class Example2 {
public static void main(String[] args) {
Apple apple = new Apple();
int pieces = apple.peel();
}
}
更多信息 参考