为了解决多重继承的问题,Java引入了接口 (interface)技术,Lisp、Ruby引入了 Mix-in 技术。
Mix-in 技术按一下规则来限制多重继承:
- 继承用但一继承;
- 第二个及两个以上的父类必须是 Mix-in 的抽象类。
- 不能单独生成实例;
- 不能继承普通类。
class TagMixin(object):
def add_tag(self, tag_id):
sql = ('insert into target_tagged'
' (target_id, target_kind, tag_id, creation_time) '
'values (?, ?, ?, CURRENT_TIMESTAMP)')
params = (self.ident, self.kind, tag_id)
storage.execute(sql, params)
storage.commit()
def get_tags(self):
sql = ('select tag_id, creation_time from target_tagged '
'where target_id = ? and target_kind = ?')
params = (self.ident, self.kind)
cursor = storage.execute(sql, params)
return cursor.fetchall()
class Post(Model, TagMixin):
kind = 1001
def __init__(self, ident, title):
self.ident = ident
self.title = title
def __repr__(self):
return 'Post(%r, %r)' % (self.ident, self.title)
可以看出这里多重继承的用法是非常谨慎的:
- TagMixin 类是单一职责的
- TagMixin 类对宿主类(Post)一无所知,除了要求宿主类有 ident 和 kind 这两个属性(等价于 Java 中要求宿主类实现 Entity 接口)
- 宿主类的主体逻辑不会因为去掉 TagMixin 而受到影响,同时也不存在超类方法调用(super)以避免引入 MRO 查找顺序问题
Mixin 就是混入的意思。
和多重继承类似(其实可以把 Mixin 看作多重继承的一种在特定场景下的应用),但通常混入 Mixin 的类和 Mixin 类本身不是 is-a 的关系,混入 Mixin 类是为了添加某些(可选的)功能。自由地混入 Mixin 类就可以灵活地为被混入的类添加不同的功能。
和多重继承类似(其实可以把 Mixin 看作多重继承的一种在特定场景下的应用),但通常混入 Mixin 的类和 Mixin 类本身不是 is-a 的关系,混入 Mixin 类是为了添加某些(可选的)功能。自由地混入 Mixin 类就可以灵活地为被混入的类添加不同的功能。