起源: 最近在阅读TensorRT-LLM
的源码, 里头有一个比较关键的类GenerationMixin
。当时阅读到这里的时候有点奇怪,后缀Mixin
表示什么意思?后来在阅读《程序员修炼之道——通向务实的最高境界》一书的继承税
一节时,又遇到了Mixin
这个关键词。于是做了一番调研,形成本文。
继承税
一节提到三种技术,来尽可能避免继承
:
- 接口与协议
- 委托
- mixin与特征
什么是Mixin
mixin的思想很简单: 希望能够为类和对象提供扩展新的功能,但不用继承。 ——《程序员修炼之道》
- 上面的
继承
不是指形式上的继承, 而是继承的语义is-a
关系。从下面的例子不难发现, mixin实际上使用了继承
的形式, 但使用者和mixin不是is-a
的关系,而是-able
关系。
Mixin是面向对象程序设计语言中的类,提供了方法的实现。其他类可以访问mixin类的方法而不必成为其子类。Mixin有时被称作”included”而不是”inherited”。mixin为使用它的class提供额外的功能,但自身却不单独使用(不能单独生成实例对象,属于抽象类)。因为有以上限制,Mixin类通常作为功能模块使用,在需要该功能时“混入”,而且不会使类的关系变得复杂。使用者与Mixin不是“is-a”的关系,而是“-able”关系。
Mixin有利于代码复用又避免了多继承的复杂。使用Mixin享有单一继承的单纯性和多重继承的共有性。接口与mixin相同的地方是都可以多继承,不同的地方在于mixin是带实现的。Mixin也可以看作是带实现的interface。这种设计模式实现了依赖反转原则。 ——Wikipedia
- 多重继承会有
diamond dependency problem
,举个例子:假如B
和C
继承自A
,D
多重继承自B
和C
,如果B
和C
都override了A
中的proc
方法,但是D
没有override这一方法, 那么D
应该使用哪个proc
方法呢? - 单继承在继承层数较多的情况, 很难确定哪个父类定义了这个方法
- 使用Minxin,可以避免上述
single-inheritance class fragmentation
和mulitple-inheritance diamond dependency
Python中的Mixin
就以上图为例, GenerationMixin
定义了两个函数:
- get_transformer_layers
- prepare_basic_inputs
然后每个特定模型的XXXForCausalLM
,模型会继承(形式上)两个类, 分别是对应的XXXModel
和GenerationMixin
。单实际上具有继承语义的只是XXXModel
, GenerationMixin
只是给这个类拓展额外的功能.
C++中的Mixin
拓展阅读1的文章介绍得很详细, 可以直接参考.
拓展阅读
1 通过mixin组合功能
2 Making Python classes more modular using mixins
Comments