何时使用关联、聚合、组合和继承?

Posted

技术标签:

【中文标题】何时使用关联、聚合、组合和继承?【英文标题】:When to use association, aggregation, composition and inheritance? 【发布时间】:2017-01-20 01:53:42 【问题描述】:

我在 *** 上看到很多帖子解释了关系之间的区别:关联、聚合、组合和继承,并附有示例。但是,我更具体地对这些方法的优缺点以及何时一种方法对手头的任务最有效感到困惑。这是我一直无法真正找到好的答案。

根据论坛的指南,我询问为什么人们个人可能更喜欢使用继承而不是组合。我对每种方法中的任何客观好处/弱点特别感兴趣,尽管听起来很强大。 IE。一种方法是否比另一种方法创建的代码更具可读性,或者它是否具有更好的运行时效率等。

理想情况下,如果有人可以给我一些真实世界的例子,说明这些方法可能成功或失败,以及为什么,那将非常有助于发展我和我希望其他人的知识。

为了确保工作有一个坚实的基础,我在 Python 2 中包含了每个关系的示例。如果我对这些关系的理解实际上不正确,希望这可以避免混淆。

协会

B 类与 A 类具有周关联关系,因为它在 addAllNums 方法中使用来自 A 的特定属性。然而,这就是关系的程度。

class A(object):
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

    def addNums():
        self.b + self.c

class B(object):
    def __init__(self, d, e):
        self.d = d
        self.e = e

    def addAllNums(self, Ab, Ac):
        x = self.d + self.e + Ab + Ac
        return x

ting = A("yo", 2, 6)
ling = B(5, 9)

print ling.addAllNums(ting.b, ting.c)

聚合

B 类与 A 类形成聚合关系,因为它在初始化时引用了一个独立的 A 对象,作为其属性之一。虽然 B 对象依赖于 A,但在 B 销毁的情况下,A 将继续存在,因为它独立于 B。

class A(object):
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

    def addNums():
        self.b + self.c

class B(object):
    def __init__(self, d, e, A):
        self.d = d
        self.e = e
        self.A = A

    def addAllNums(self):
        x = self.d + self.e + self.A.b + self.A.c
        return x

ting = A("yo", 2, 6)
ling = B(5, 9, ting)

print ling.addAllNums()

作曲

与聚合很像,但是 B 不是引用一个独立的对象,而是在它自己的构造函数中将 A 的一个实例初始化为一个属性。如果 B 对象被销毁,那么 A 对象也是如此。这就是为什么组合是如此紧密的关系。

class A(object):
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

    def addNums():
        self.b + self.c

class B(object):
    def __init__(self, d, e):
        self.d = d
        self.e = e
        self.A = A("yo", 2, 6)

    def addAllNums(self):
        x = self.d + self.e + self.A.b + self.A.c
        return x

ling = B(5, 9)

print ling.addAllNums() 

我决定不包含继承的示例,因为我对它非常满意,而且我觉得包含它可能会使问题的重点有点离题。

不管上面的例子和继承有什么优缺点(相互比较)。

谢谢。

【问题讨论】:

【参考方案1】:

我的个人意见是,您应该首先考虑如何以有助于解决特定现实世界问题的方式对现实世界数据进行建模。将事物分配给类,描述类和/或实例之间的关系,描述事物的属性等是困难的部分:正确地做到这一点,代码中的模式(无论是继承、聚合、子类化等)变得容易。例如:

正方形和长方形有什么关系? 可逆矩阵是方阵的子类吗? 死牛是哺乳动物吗 学生是人的子类吗?老师是子班吗?助教呢?

【讨论】:

我认为问题在于我没有真正处理现实世界的对象。例如。如果我在汽车经销店工作,一辆车会和a有组成关系:方向盘、轮胎等,因为这些元素不存在于车外。毕竟,你不能卖给别人一辆新车,而是决定保留尾气。同样,如果我在车库工作,我可以通过拆解毁掉一辆汽车,但排气仍然是独立存在的;进行关系聚合。但是,当我在处理概念对象时,似乎事情并不是那么清晰......【参考方案2】:

根据wikipedia 的经验法则是,随着时间的推移,或者随着概念模型的细节越来越多,关系会变得柔和,即组合变成聚合,聚合变成关联,例如引擎最初可能是汽车的组合但是当您添加功能时,引擎可以从一辆车转移到另一辆车,使其成为一个聚合。

所以要回答您关于每种方法的优缺点的问题,更多的是您正在建模的关系的问题,类似于我应该将名称存储为字符串还是数字的问题

【讨论】:

以上是关于何时使用关联、聚合、组合和继承?的主要内容,如果未能解决你的问题,请参考以下文章

UML类图关系(泛化、继承、实现、依赖、关联、聚合、组合)

合成(组合)/聚合复用原则

UML中的6大关系(关联依赖聚合组合泛化实现)

面向对象——对继承关联聚合组合依赖的理解

UMLUML类图关系(泛化 继承实现依赖关联聚合组合)

依赖关联聚合和组合之间区别