我经常听到(并在这个网站上读到)很多关于“优先选择组合而不是继承”的话题。
但是什么是组合?我从人类:哺乳动物:动物的角度理解继承,但是我真的找不到组合的定义……有人可以帮我吗?
我经常听到(并在这个网站上读到)很多关于“优先选择组合而不是继承”的话题。
但是什么是组合?我从人类:哺乳动物:动物的角度理解继承,但是我真的找不到组合的定义……有人可以帮我吗?
组合指将简单类型组合成更复杂的类型。在您的示例中,组合可能是:
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
这种方法的优势在于类型和不必符合它们之前父类的接口。这可能是一件好事,因为有时超类的更改会对子类产生严重影响。它们仍然可以通过私有实例访问这些类的属性和行为,如果想公开这些以前的超类行为,只需将其包装在公共方法中即可。
我在这里找到了一个带有良好示例的链接:http://www.artima.com/designtechniques/compoinh.html组合(Composition)是指构成整体的各个部分。汽车由轮子、发动机和座位等部件组成。继承(Inheritance)是“是一个”("is a")关系。而组合则是“有一个”("has a")关系。
给一个类赋予行为有三种方法。你可以将该行为编写到类中;你可以从具有所需行为的类继承;或者,你可以将具有所需行为的类作为字段或成员变量合并到你的类中。后两种表示代码重用的形式,而最后一种——组合——通常更受欢迎。它实际上并没有为您的类提供所需的行为——您仍然需要在字段上调用方法——但它对您的类设计施加的约束较少,并且导致易于测试和调试的代码。继承有其地位,但应首选组合。
class Engine
{
}
class Automobile
{
}
class Car extends Automobile // car "is a" automobile //inheritance here
{
Engine engine; // car "has a" engine //composition here
}
组合 - 对象的功能由不同类的集合组成。在实践中,这意味着持有对另一个类的指针,以将工作推迟到该类。
继承 - 对象的功能由它自己的功能加上父类的功能组成。
至于为什么组合比继承更受欢迎,请参考椭圆圆问题。
组合的一个例子是在一个类的实例中包含另一个类,而不是从它继承。
这个页面有一篇很好的文章解释了为什么人们说“偏向于组合而非继承”,并且提供了一些例子来说明。
组合
简单地说,组合是使用实例变量作为对其他对象的引用。
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应用程序
时,它会打印出"Peeling is appealing.",因为Apple继承(重用)了Fruit的peel()
实现。然而,如果在将来的某个时候,您希望将peel()
的返回值更改为Peel类型,那么您将破坏Example1
的代码。即使Example1直接使用Apple并且从未明确提到Fruit,您对Fruit的更改也会破坏Example1的代码。
更多信息请参考ref。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
的peel()
实现。与扩展Fruit
不同,Apple
可以持有对Fruit
实例的引用,并定义自己的peel()
方法,只需在Fruit
上调用peel()
即可。以下是代码:
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();
}
}
获取更多信息ref
类B
内部创建一个类A
对象(而不是将类B
从类A
继承)"? - geekayw69rdy
后来回答了它。是的,我可以这么说。 - geekay