为什么使用组合?

7 浏览
0 Comments

为什么使用组合?

这个问题的答案已经在这里有了:

优先选择组合而不是继承?

我一直在寻找关于组合的简单代码示例的答案。我知道组合和继承的差异,但我无法通过代码理解它们。

有关为什么我应该使用组合的比较示例(使用两种方法)将非常有帮助。

提前致谢

admin 更改状态以发布 2023年5月20日
0
0 Comments

基本区别在于继承在编译时固定了类的层次结构,而组合允许在运行时决定组合类的关系。

在继承中,代码与继承层次结构固定。例如,如果我们从 Shape 类继承 Circle 类,则 Shape 将被固定为 Circle 类的基类。

假设,我们进一步将 Shape 分为 2DShape 和 3DShape。现在在继承中,Circle 类无法从 2DShape 继承。

使用组合就可以。因此,您可以在运行时将组合的类更改为任何组合类的派生类型。

0
0 Comments

您可能想要查看组合优于继承

优先使用组合而不是继承是一种设计原则,可为设计提供更高的灵活性,为业务领域类提供更稳定的业务领域,并使其具有长期的优势。换句话说,HAS-A关系比IS-A关系更好。

查看aleemb相关帖子中的答案,其中解释了代码示例的差异

这里有一个有用的链接,可以解释为什么喜欢组合而不是继承

尽管组合和继承都允许您重用代码,但继承的缺点之一是它会破坏封装性。如果子类依赖于超类的行为进行操作,它会突然变得脆弱。当超类的行为发生变化时,子类中的功能可能会被破坏,而子类本身没有发生任何变化。继承使代码变得脆弱的一个例子是来自HashSet的方法add()和addAll()。假设,如果 HashSet的addAll()方法是通过调用add()方法实现的,并且您编写了一个HashSet的子类,在将内容插入HashSet之前对其进行加密。由于只有一个可以将对象插入HashSet的方法add(),您通过覆盖add()方法并调用encrypt()方法来覆盖这些方法。这也自动涵盖了addAll(),因为addAll()是使用add()实现的,看起来很吸引人。如果您仔细看,就会发现这种实现是脆弱的,因为它依赖于超类的行为。如果基类想要提高性能并实现addAll()而不调用add()方法,则下面的例子将会出现问题。

public class EncryptedHashSet extends HashSet{
.....
public boolean add(Object o) {
   return super.add(encrypt(o));
}
}

如果您使用了组合而不是继承,您将不会遇到这个问题,并且您的类会更加健壮,因为您不再依赖于超类的行为。相反,您正在使用超类方法进行附加部分,并且您将受益于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));
}
.......
}

0