在Ruby中覆盖Spaceship运算符时实际发生了什么?

时间:2015-03-27 19:01:53

标签: ruby operators comparison-operators spaceship-operator

我是Ruby新手。有人可以解释一下< =>方法适用于以下程序。 '其他'参数在下面使用?

class Age
  attr_reader :value

  def initialize(value)
  @value = value
  end

  def <=> (other) # What is actually happening here...
  self.value <=> other.value # ..and here?
  end

end

a = Age.new(7)
b = Age.new(3)
c = Age.new(9)

d = [a, b, c]
puts d.sort

1 个答案:

答案 0 :(得分:0)

让我们从d.sort开始。 d是一个数组,因此您应该阅读Array#sort。文档说明排序&#34;将使用<=>运算符&#34;完成。这意味着在对数组进行排序时,它将重复评估x <=> y xyd的不同元素,以确定哪些元素更大/更小。

Ruby中的运算符有点棘手,因为它们实际上是伪装的方法调用。 x <=> y只是写x.<=>(y)的另一种方式。也就是说,x有一个名为<=>的方法,它作为参数传递y。由于d的元素是Age类的实例,Age需要定义实例方法<=>。因此,当您看到def <=> (other)时,这与正常的方法定义(def foo(other))没有什么不同,但使用不同的方法名称。

现在我们正在为<=>个实例定义Age,该方法实际应该做什么?那么每个Age对象都存储@value,所以直观地Age#<=>应该比较@value。这是self.value <=> other.value的作用。这是有效的,因为value返回Fixnum,幸运的是Fixnum#<=>内置于Ruby中以进行正确的比较。

有关幕后发生的事情的示例,我们可以尝试对包含我们不知道如何比较的值的数组进行排序:

[Age.new(3), 4].sort
# NoMethodError: undefined method `value' for 4:Fixnum
[4, Age.new(3)].sort
# ArgumentError: comparison of Fixnum with Age failed

这显示了对不同类型的排序如何导致调用不同的<=>方法。