子类化内置类型
- 内置类型 dict 有 _init_ 和 _update_ 方法,但子类 DoppelDict 的 _setitem_ 应覆盖这些方法,却没有覆盖。
- 违反面向对象编程原则:应始终从实例(self)所属的类开始搜索方法
- 不要子类化内置类型(如 dict、list、str),因为内置类型的方法通常会忽略子类覆盖的方法
- 因此,子类应继承 collections 模块(如 UserDict、UserList、UserString)
多重继承和方法解析顺序
- MRO(Method Resolution Order)方法解析顺序
- 定义类 C 时,括号内父类 A 写在 B 前面。
那么对于 C 来说,如果 A、B 存在同名方法,根据 MRO 应该先调用 A 的方法 - 直接在类上调用实例方法时,必须显式传入 self 参数,因为这样的访问是未绑定方法(unbound method)
- super() 调用父类方法时,遵循 MRO 原则
处理多重继承
- 区分接口继承和实现继承
接口继承:是为了具体化父类
实现继承:是为了得到父类的一些方法、属性 - 使用抽象基类显式表示接口
如果类的作用是定义接口,应该明确地把它定义为抽象基类,即 abc.ABC 或其他抽象基类的子类。 - 通过 mixin 重用代码
如果一个类的作用是为多个不相关子类提供方法实现,那么就应该把这个类定义为 mixin 类。
mixin 类不定义新类型,不能实例化,只是打包方法,便于重用。
其中,打包的方法应该体现某方面的行为。且子类不能只继承 mixin 类。 - 不要子类化多个具体类
作为父类的具体类应该没有或最多一个,其余的都是抽象基类或 mixin - 聚合类(aggregate class)
继承多个抽象基类或 mixin,而类定义体为空。 - 优先使用对象组合,而不是类继承
通过父类的实例也可以调用相应的方法,而不必动用继承。
因为子类化是一种紧耦合,较高的继承树脆弱。