「 mixin 」 这个概念,在 Ruby 中有,在 Python 中也有,有时候会看到有些文章翻译成 「 混入 」,但更多的是直接使用 mixin 。因此,本文就直接使用 mixin 而不翻译为 「 混入 」 了
mixin 、extend 和 composite
在继续讲解 mixin 之前,我们先来区分下 「 mixin 」 、继承/扩展 ( extend ) 和组合 ( composite ),这三者代表啥意思呢?
它们代表的是一个类和另一个类之间产生关系的几种机制:
- 一个类是另一个类的祖先类,这种用的是 扩展 extend
- 两个之间并没有任何关系,只是在一个类的方法中会实例化另一个类,这是 组合
- 一个类和另一个类之间没有任何关系,只是在实例化的时候结合了另一个类,这种就是 mixin
这个说明有点不恰当,不过大概意思已经到了。
要充分理解三者的区别,就要从它们之实例化之前有没有关系,实例化时的相互关系方面着手
Comparable mixin
回到我们的正题,我们今天要讲解的是 Comparable
mixin 。Compare
mixin 是 Ruby 核心的重要组成部分。
它通常用于需要比较的类中,包含了一堆用于对象比较目的的方法
例如,Numeric
和 String
类包含此 mixin
irb> Numeric.ancestors => [Numeric, Comparable, Object, Kernel, BasicObject] irb> String.ancestors => [String, Comparable, Object, Kernel, BasicObject]
如果你想了解更多
Module#ancestors
方面的知识,可以访问我们的另一篇文章 Ruby 中的对象模型 ( object model ) ( 上 )
包含 Comparable 的类的实现
假设我们要根据 rank
属性来比较一些 profiles ( 用户资料 )
class Profile include Comparable attr :rank def initialize(rank) @rank = rank end def <=>(other_profile) rank <=> other_profile.rank end end irb> profile21 = Profile.new(21) => #<Profile:0x0404 @rank=21> irb> profile42 = Profile.new(42) => #<Profile:0x0404 @rank=42> irb> profile84 = Profile.new(84) => #<Profile:0x0404 @rank=84> irb> profile84 > profile42 => true irb> profile84 < profile42 => false irb> profile84 == profile84 => true irb> profile21 <= profile42 => true irb> profile84 >= profile42 => true
包含 Comparable mixin 的类必须响应 <=>
方法( 也称为太空船运算符 )。
太空船运算符方法是非常重要的,因为它是 Comparable mixin 中其它方法的基础方法 ,例如 ==
,<=
,>=
,>
,<
等等
由于 rank
属性是一个整型 ( Integer ),也就是 Numeric 类的直接子元素,因此可以使用 Numeric 实现的 <=>
方法安全的比较每个 rank
属性