覆盖 == 相等运算符仅在一个方向上有效

Overriding == equality operator works only in one direction

考虑下一个例子,我不断地将 == 运算符重写为 return true

class Example
  def ==(other)
    return true
  end
end

但是,这只适用于一个方向:

exp = Example.new
puts exp == {} #=> true
puts {} == exp #=> false

有没有办法强制这个相等方法在相反的方向起作用?

不更改其他 classes 是不可能的。基本上 a == b 等于 a.==(b)。所以如果你想让它工作,你需要覆盖第二个 class 的 == 运算符。

Is there a way to force this equality method to also work in the reverse direction?

否,但您可以更改 Hash#== 以识别 Example 的特殊情况。

class Example
  def ==(other)
    return true
  end
end

class Hash
  alias_method :original_double_equals, :==

  def ==(other)
    case other
    when Example
      other == self
    else
      original_double_equals(other)
    end
  end
end


exp = Example.new
exp == {} # => true
{} == exp # => true
{} == {} # => true
{foo: 1} == {foo: 2} # => false

如果我是你,我不会这样做。

不,不可能。

Ruby是一种面向对象的语言。 OO 的基本思想 是您向对象和接收者对象发送消息,只有接收者 对象才能决定如何响应那条消息。

  • 如果您将消息 == 发送到对象 a,将对象 b 作为参数传递,则 a a 独自一人 决定如何回应。
  • 如果您将消息 == 发送到对象 b,将对象 a 作为参数传递,则 b b 独自一人 决定如何回应。

唯一的方法保证给出相同的响应,是如果ab合作并且同意 给出相同的响应。

理论上可以设计一种语言,使 a == b 不是发送给 ab 的消息,而是发送给某些人的消息第三"context object"。 IOW,a == b 不被解释为 a.==(b)b.==(a),而是 some_context_object.==(a, b)(例如,上下文对象可能只是你自己,即 self.==(a, b))。在这种情况下,上下文对象可以访问 abpublic API 并且可以采取措施确保== 是可交换的。

但一般来说,根据 OO 的基本性质,消息是不可交换的,接收者对象是特殊的。