关于python:何时使用关联,聚合,组合和继承?

When to use association, aggregation, composition and inheritance?

我在StackOverflow上看到了很多文章,用例子解释了关系之间的区别:关联、聚合、组合和继承。然而,我更具体地感到困惑的是,每种方法的优缺点,以及当一种方法对手头的任务最有效时。这是我一直没能找到一个好答案的问题。

例如,为了与论坛的指导方针保持一致,我不想问为什么人们个人更喜欢使用继承而不是组合。我对每种方法的任何客观好处/缺点都特别感兴趣,尽管听起来很强。也就是说,一种方法是否比另一种方法创建更可读的代码,或者它是否具有更好的运行时效率等。

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

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

联想

类B与类A有一周的关联关系,因为它使用addallnums方法中a的特定属性。然而,这就是关系的范围。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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并没有引用独立的对象,而是将自己的构造函数中的实例初始化为属性。如果B对象被销毁,那么A对象也会被销毁。这就是为什么构图是如此强烈的关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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()

我已经决定不包括继承的例子,因为我对它非常满意,而且我觉得它的包含可能会使问题的要点偏离正切一点。

不管怎样,同样地,上面的例子和继承(相比之下)有什么利弊。

谢谢。


根据维基百科的经验法则,关系会随着时间的推移而软化,或者随着概念模型的细节的增加而软化,也就是说,组成会变成聚合,聚合会变成关联,例如,引擎最初可能是一辆车的组成,但是当你添加功能时,引擎可以从一辆车转移到另一辆车上。o另一个使其成为聚合。

因此,为了回答你对每种方法的利弊的问题,这更像是你正在建模的关系的问题,类似于我应该将名称存储为字符串或数字的问题


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

正方形和长方形之间的关系是什么?可逆矩阵是方阵的一个子类吗?死牛是哺乳动物吗?学生是人的一个子类吗?老师是一个子类吗?TAs呢?