我一直在寻找一个关于组合的简单代码示例的答案。我知道组合和继承的差异,但我无法使用代码来解决它。
任何基于比较的示例(使用两种方法)都是非常有用的。
提前致谢
答案 0 :(得分:1)
基本区别在于,继承在编译时修复了类层次结构,而组合允许在运行时决定组合类关系。
使用继承,它使用继承层次结构修复的代码。例如,如果我们从Circle
类继承Shape
类,Shape
将被修复为Circle
类的基类。
假设我们进一步将Shape分类为2DShape
和3DShape
。现在有了继承,Circle
类无法继承2DShape
。
使用Composition可以。因此,您可以在运行时将组合类更改为任何派生类型的组合类。
答案 1 :(得分:1)
您可能想查看 Composition over inheritance
赞成合成而不是继承是一种设计原则 为设计提供更高的灵活性,提供业务领域类 从长远来看,业务领域更加稳定。 换句话说, HAS-A可能比IS-A关系更好
在 related post 中查看 aleemb 的答案,其中他解释了与代码示例的区别
这是一个有用的link,它解释了为什么更喜欢合成而不是继承
尽管Composition和Inheritance都允许您重用代码,但继承的一个缺点是它会破坏封装。如果子类依赖于其操作的超类行为,它会突然变得脆弱。当超类的行为发生变化时,子类中的功能可能会被破坏,而不会发生任何变化。使代码易碎的继承的一个例子是来自HashSet的方法add()和addAll()。假设,如果HashSet的addAll()是通过调用add()方法实现的,那么你编写了一个HashSet子类,它在插入HashSet之前对内容进行加密。由于只有一个方法add(),它可以将对象插入HashSet,您可以覆盖这些方法并通过覆盖add()调用您的encrypt()方法。这也会自动覆盖addAll(),因为addAll()是使用add()实现的,它看起来非常诱人。如果仔细观察,你会发现这个实现很脆弱,因为它依赖于超类行为。如果基类想要提高性能并在不调用add()方法的情况下实现addAll(),则下面的示例将会中断。
public class EncryptedHashSet extends HashSet{
.....
public boolean add(Object o) {
return super.add(encrypt(o));
}
}
如果您使用了Composition来支持继承,那么您将不会遇到这个问题而且您的Class会更强大,因为您不再依赖于超类行为了。相反,你使用超类方法作为加法部分,你将受益于addAll()的任何改进,如下例所示:
public class EncryptedHashSet implements Set{
private HashSet container;
public boolean add(Object o) {
return container.add(encrypt(o));
}
public boolean addAll(Collection c) {
return conatainer.add(encrypt(c));
}
.......
}
答案 2 :(得分:0)
我认为Joshua Bloch说得最好:Item 16: Favor composition over inheritance