什么是在ruby中实现平等的正确方法

Pet*_*son 50 ruby equality

对于一个简单的类似结构的类:

class Tiger
  attr_accessor :name, :num_stripes
end
Run Code Online (Sandbox Code Playgroud)

什么是正确实现平等,以确保以正确的方式==,===,eql?,等工作,使在很好的集合类游戏的情况下,哈希等.

编辑

另外,当你想根据未暴露在类之外的状态进行比较时,实现相等性的好方法是什么?例如:

class Lady
  attr_accessor :name

  def initialize(age)
    @age = age
  end
end
Run Code Online (Sandbox Code Playgroud)

在这里,我希望我的平等方法考虑到@age,但是Lady并没有将她的年龄暴露给客户.在这种情况下我是否必须使用instance_variable_get?

Way*_*rad 69

要简化具有多个状态变量的对象的比较运算符,请创建一个方法,将所有对象的状态作为数组返回.然后只比较两种状态:

class Thing

  def initialize(a, b, c)
    @a = a
    @b = b
    @c = c
  end

  def ==(o)
    o.class == self.class && o.state == state
  end

  protected

  def state
    [@a, @b, @c]
  end

end

p Thing.new(1, 2, 3) == Thing.new(1, 2, 3)    # => true
p Thing.new(1, 2, 3) == Thing.new(1, 2, 4)    # => false
Run Code Online (Sandbox Code Playgroud)

此外,如果您希望类的实例可用作哈希键,则添加:

  alias_method :eql?, :==

  def hash
    state.hash
  end
Run Code Online (Sandbox Code Playgroud)

这些都需要公开.

  • 我真的很喜欢通过委托比较与状态数组来比较对象的技巧. (2认同)
  • @kraftydevil 这确实很不幸。对此我很抱歉。 (2认同)
  • 像这样的类比较怎么样:`o.is_a?(self.class)`?我知道它的行为方式(后代),但我正在寻找最佳实践。 (2认同)

jve*_*zia 20

要一次测试所有实例变量的相等性:

def ==(other)
  other.class == self.class && other.state == self.state
end

def state
  self.instance_variables.map { |variable| self.instance_variable_get variable }
end
Run Code Online (Sandbox Code Playgroud)

  • 这确实更好,因为它确保您不会意外地遗漏任何变量.现在,自动使用每个实例变量可能还会产生一些意想不到的后果,但我不确定也不会知道,直到有一天它让我感到惊讶. (3认同)