Python: 继承还是组合
假设我有一个 class
,它使用了一些 dict
的功能。我之前是把一个 dict
对象放在里面,然后从外部访问它,但最近我想到了一个新主意,就是直接继承 dict
,然后添加一些我可能需要的属性和方法。这样做好吗?还是说我应该继续使用组合的方式?
4 个回答
3
这两种方法都不错,但我更喜欢继承,因为这样代码会更少(只要代码可读,少一些总是好的)。
在 Python 2.2 及之前的版本,你不能直接从内置类型继承,所以你必须使用组合的方式。
class FileInfo(dict): "store file metadata" def __init__(self, filename=None): self["name"] = filename
- 第一个区别是你不需要导入 UserDict 模块,因为 dict 是一个内置的数据类型,随时可以用。第二个区别是你是直接从 dict 继承,而不是从 UserDict.UserDict 继承。
- 第三个区别虽然不太明显,但很重要。由于 UserDict 的内部工作方式,你需要手动调用它的
__init__
方法来正确初始化它的内部数据结构。而dict
不是这样,它不是一个包装器,不需要明确的初始化。
3
你真的需要好好考虑一下你想做的事情的成本和范围。如果你只是想要字典那样的行为,直接从 dict
继承是简单又快速的,但这样做会有一些限制,比如会导致你用这个类创建的对象不能被哈希。
举个例子,如果你需要把对象序列化(也就是用 pickle
),同时又想要字典那样的功能,那么显然你不能直接从 dict
继承,这时候你就需要把你想要的功能组合起来,才能实现你的需求。
14
继承这个概念常常被滥用。除非你的类是为了作为一个带有额外功能的通用字典,否则我建议使用组合的方式。
仅仅为了节省调用的时间,通常并不足以选择继承。
来自设计模式书中的一句话:
更倾向于使用对象组合,而不是类继承。
理想情况下,你不应该为了实现重用而创建新的组件。你应该能够通过组合现有的组件来获得所需的所有功能。但实际上,这种情况很少发生,因为可用的组件集合往往不够丰富。通过继承来重用可以更容易地创建新的组件,以便与旧组件组合。因此,继承和对象组合是可以一起工作的。
然而,我们的经验是,设计者往往过度使用继承作为重用的手段,而通过更多依赖对象组合,设计通常会变得更可重用(也更简单)。