对于这种特定情况,Python中的继承与组合?

时间:2016-08-28 03:21:55

标签: python inheritance combinations

假设我有一系列课程如下:

class A(object):
    __init__(self,a):
        self.a=a
class B(A):
    __init__(self,a,b):
        super(B,self).__init__(a)
        self.b=b
class C(A):
    __init__(self,a,c1,c2):
        super(C,self).__init__(a)
        self.c1=c1
        self.c2=c2

如果现在D是B和C,它可以实现为

class D(B,C)
    __init__(self,a,b,c1,c2,d):
        pass

D可以理解为BC的组合

class D(B,C)
    __init__(self,a,b,c1,c2,d):
        self.b=B(a,b)
        self.c=C(a,c)

似乎比多继承案例复杂一点。

嗯,现在让我们的成像class D2由5件B和3件C组合而成,class D3D2加上一个额外的C(参数与D中的参数不同),D4D2和另外两个C组成(另外2个) C具有相同的参数,但与D2中的参数不同。使用合成似乎D2是好的,但D3使用D2C的继承是好的,D4可以使用{的继承{1}}和D2

对我来说,使用组合的缺点是我必须编写C而不是d.c.c1(如在继承的情况下)来获取参数d.c1或者我需要存储直接在D中的参数c(除了作为c的那个)。是否有任何哲学上一致的方式来处理这些类?谢谢!

1 个答案:

答案 0 :(得分:2)

你必须对这样的问题得到一定程度的意见 - 我的答案是使用继承 iff 你的类被设计为继承。在所有其他情况下使用组合。在实践中,这通常意味着如果您扩展的代码存在于您的控制范围之外,请不要将其子类化,除非他们的文档谈论如何您可以有效地将其子类化。

在这种情况下,由于您似乎是类层次结构的作者,继承似乎有意义(尽管您的一些断言不正确 - D并不像您想象的那样容易实现因为没有超级类__init__会被调用。您可能应该熟悉Raymond Hettinger的"super considered super" article

中的设计模式
class A(object):
    def __init__(self, a, **kwargs):
        super(A, self).__init__(**kwargs)
        self.a = a

class B(A):
    def __init__(self, b, **kwargs):
        super(B, self).__init__(**kwargs)
        self.b = b

class C(A):
    def __init__(self, c1, c2, **kwargs):
        super(c, self).__init__(**kwargs)
        self.c1 = c1
        self.c2 = c2

现在 D的实现非常简单:

class D(B, C):
    pass

请注意,我们甚至不需要定义__init__,因为超类的所有构造函数都可以接受任意关键字参数。实例化D看起来像:

d = D(a='a', b='b', c1='c1', c2='c2')