面向对象编程中的混合类型mixins技术

在面向对象的编程语言中,mixin(或mix-in)是一个包含供其他类使用的方法的类,而不必是这些其他类的父类。这些其他类如何访问 mixin 的方法取决于语言。Mixin 有时被描述为“包含”而不是“继承”。

Mixins 鼓励代码重用,可用于避免多重继承可能导致的继承歧义(“菱形问题”),或解决语言中缺乏对多重继承的支持。一个 mixin 也可以被看作是一个实现了方法的接口。这种模式是实施依赖倒置原则的一个例子。

历史

Mixins 最早出现在Symbolics的面向对象的Flavors系统(由 Howard Cannon 开发)中,这是Lisp Machine Lisp中使用的一种面向对象的方法。这个名字的灵感来自马萨诸塞州萨默维尔的史蒂夫冰淇淋店: 冰淇淋店的老板提供了一种基本口味的冰淇淋(香草、巧克力等),并混合了一些额外的物品(坚果、饼干、软糖等),并将该物品称为“混合”,这是他当时自己的商标术语。

定义

Mixins 是一种语言概念,它允许程序员将一些代码注入到一个类中。Mixin 编程是一种软件开发风格,其中功能单元在一个类中创建,然后与其他类混合。

mixin 类充当父类,包含所需的功能。然后子类可以继承或简单地重用此功能,但不能作为专门化的手段。通常,mixin 会将所需的功能导出到子类,而不会创建严格的、单一的“是”关系。这就是 mixins 和继承概念之间的重要区别,因为子类仍然可以继承父类的所有特性,但是关于子类“是一种”父类的语义不一定要应用。

优势

  1. 它提供了一种多重继承机制,允许一个类使用来自多个类的通用功能,但没有多重继承的复杂语义。
  2. 代码可重用性:当程序员想要在不同的类之间共享功能时,Mixins 很有用。无需一遍又一遍地重复相同的代码,可以简单地将通用功能分组到一个 mixin 中,然后将其包含到每个需要它的类中。
  3. 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