Python 中针对此特定情况的继承与组合?
Inheritance vs. Composition in Python for this specific case?
假设我有一系列 类 如下:
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
可以理解为B
和C
的组合
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 D3
是由[=21=组成的]加上一个额外的C
(与D
中的参数不同),D4
由D2
和2个额外的C
组成(这些2 个额外的 C
具有相同的参数,但与 D2
中的不同。好像D2
好用组合,但是D3
好用D2
和C
的继承,D4
好用[的继承=21=] 和 C
。
对我来说,使用组合的缺点是我必须写 d.c.c1
而不是 d.c1
(在继承情况下)来获取参数 c
或者我需要将参数c
直接存入D(d.c.c1
除外)。有什么哲学上一致的方法来处理这些类?谢谢!
您一定会对这样的问题获得某种程度的意见 -- 我的答案是使用继承 iff 您的 classes 被设计为遗传。在所有其他情况下使用组合。实际上,这通常意味着如果您要扩展的代码存在于您无法控制的领域,请不要将其子class,除非他们的文档谈到如何您可以有效地subclass它。
在这种情况下,由于您似乎是 class 层次结构的作者,继承似乎是有道理的(尽管您的某些断言不正确 - D
并不那么容易按照您的设想实施,因为 superclass __init__
的 none 将被调用)。您可能应该熟悉 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__
,因为所有超 classes 的构造函数都可以接受任意关键字参数。实例化一个 D
看起来像:
d = D(a='a', b='b', c1='c1', c2='c2')
假设我有一系列 类 如下:
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
可以理解为B
和C
的组合
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 D3
是由[=21=组成的]加上一个额外的C
(与D
中的参数不同),D4
由D2
和2个额外的C
组成(这些2 个额外的 C
具有相同的参数,但与 D2
中的不同。好像D2
好用组合,但是D3
好用D2
和C
的继承,D4
好用[的继承=21=] 和 C
。
对我来说,使用组合的缺点是我必须写 d.c.c1
而不是 d.c1
(在继承情况下)来获取参数 c
或者我需要将参数c
直接存入D(d.c.c1
除外)。有什么哲学上一致的方法来处理这些类?谢谢!
您一定会对这样的问题获得某种程度的意见 -- 我的答案是使用继承 iff 您的 classes 被设计为遗传。在所有其他情况下使用组合。实际上,这通常意味着如果您要扩展的代码存在于您无法控制的领域,请不要将其子class,除非他们的文档谈到如何您可以有效地subclass它。
在这种情况下,由于您似乎是 class 层次结构的作者,继承似乎是有道理的(尽管您的某些断言不正确 - D
并不那么容易按照您的设想实施,因为 superclass __init__
的 none 将被调用)。您可能应该熟悉 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__
,因为所有超 classes 的构造函数都可以接受任意关键字参数。实例化一个 D
看起来像:
d = D(a='a', b='b', c1='c1', c2='c2')