面向对象编程中的混合类型mixins技术
在面向对象的编程语言中,mixin(或mix-in)是一个包含供其他类使用的方法的类,而不必是这些其他类的父类。这些其他类如何访问 mixin 的方法取决于语言。Mixin 有时被描述为“包含”而不是“继承”。
Mixins 鼓励代码重用,可用于避免多重继承可能导致的继承歧义(“菱形问题”),或解决语言中缺乏对多重继承的支持。一个 mixin 也可以被看作是一个实现了方法的接口。这种模式是实施依赖倒置原则的一个例子。
历史
Mixins 最早出现在Symbolics的面向对象的Flavors系统(由 Howard Cannon 开发)中,这是Lisp Machine Lisp中使用的一种面向对象的方法。这个名字的灵感来自马萨诸塞州萨默维尔的史蒂夫冰淇淋店: 冰淇淋店的老板提供了一种基本口味的冰淇淋(香草、巧克力等),并混合了一些额外的物品(坚果、饼干、软糖等),并将该物品称为“混合”,这是他当时自己的商标术语。
定义
Mixins 是一种语言概念,它允许程序员将一些代码注入到一个类中。Mixin 编程是一种软件开发风格,其中功能单元在一个类中创建,然后与其他类混合。
mixin 类充当父类,包含所需的功能。然后子类可以继承或简单地重用此功能,但不能作为专门化的手段。通常,mixin 会将所需的功能导出到子类,而不会创建严格的、单一的“是”关系。这就是 mixins 和继承概念之间的重要区别,因为子类仍然可以继承父类的所有特性,但是关于子类“是一种”父类的语义不一定要应用。
优势
- 它提供了一种多重继承机制,允许一个类使用来自多个类的通用功能,但没有多重继承的复杂语义。
- 代码可重用性:当程序员想要在不同的类之间共享功能时,Mixins 很有用。无需一遍又一遍地重复相同的代码,可以简单地将通用功能分组到一个 mixin 中,然后将其包含到每个需要它的类中。
- Mixins 只允许继承和使用来自父类的所需特性,而不一定是来自父类的所有特性。[9]
实现
在Simula中,类定义在一个块中,其中属性、方法和类初始化都定义在一起;这样一个类上可以调用的所有方法都定义在一起,类的定义就完成了。
在Flavors中,mixin 是一个类,另一个类可以从该类继承槽定义和方法。mixin 通常没有直接实例。由于 Flavor 可以从多个其他 Flavor 继承,因此它可以从一个或多个 mixin 继承。请注意,原始 Flavors 没有使用泛型函数。
在 New Flavors(Flavors 的继承者)和CLOS中,方法被组织在“通用函数”中。这些泛型函数是通过类调度和方法组合在多种情况(方法)中定义的函数。
CLOS 和 Flavor 允许 mixin 方法向现有方法添加行为::before以及:afterFlavor 中的守护进程、whopper 和包装器。CLOS 添加了:around方法和通过CALL-NEXT-METHOD. 因此,例如,stream-lock-mixin 可以围绕流类的现有方法添加锁定。在 Flavors 中,人们会编写一个 wrapper 或 whopper,而在 CLOS 中,人们会使用一种:around方法。CLOS 和 Flavors 都允许通过方法组合计算重用。:before,:after和:around方法是标准方法组合的一个特征。提供了其他方法组合。
一个例子是+方法组合,其中泛型函数的每个适用方法的结果值被算术添加以计算返回值。例如,它与图形对象的边界混合一起使用。图形对象可能具有通用宽度函数。border-mixin 会在对象周围添加一个边框,并有一个计算其宽度的方法。一个新类bordered-button(既是图形对象又使用bordermixin)将通过调用所有适用的宽度方法来计算其宽度——通过+方法组合。添加所有返回值并创建对象的组合宽度。
在一篇 OOPSLA 90 论文中,Gilad Bracha 和 William Cook 将 Smalltalk、Beta 和 CLOS 中发现的不同继承机制重新解释为 mixin 继承的特殊形式。
使用 mixin 的编程语言[编辑]
除了 Flavors 和 CLOS(Common Lisp的一部分),一些使用 mixin 的语言是:
- Ada(通过使用泛型中的任意操作扩展现有的标记记录)
- C#(自 C# 8.0 起,通过接口的默认方法)[11]
- Corba
- ColdFusion(基于类使用包含和基于对象,通过在运行时将方法从一个对象分配给另一个对象)
- Curl(带Curl RTE)
- D(称为“模板混合”;D 还包括将字符串编译为代码的“混合”语句。)
- Dart
- Factor
- Groovy
- Java(从 Java 8 开始,通过接口的默认方法)
- JavaScript 委托 - 作为角色的函数(Traits 和 Mixins)
- kotlin
- Less
- OCaml
- Perl(通过Perl 5 对象系统的 Moose 扩展中的角色)
- PHP “traits”
- Magik
- MATLAB
- Python
- Racket(mixins 文档)
- Raku
- Rust
- Ruby
- Scala
- XOTcl / TclOO (内置于Tcl的对象系统)
- Sass(一种样式表语言)
- Smalltalk
- Vala
- Swift
- SystemVerilog
- TypeScript(混合文档)
分类: 默认 标签: 发布于: 2022-06-22 10:36:56, 更新于: 2022-06-22 10:36:56