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

时间:2009-12-19 01:20:56

标签: ruby equality

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

class Tiger
  attr_accessor :name, :num_stripes
end

正确实现相等性的正确方法是什么,以确保=====eql?等工作,并使类的实例在集合,哈希中很好地发挥作用等等。

修改

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

class Lady
  attr_accessor :name

  def initialize(age)
    @age = age
  end
end

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

3 个答案:

答案 0 :(得分:67)

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

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

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

  alias_method :eql?, :==

  def hash
    state.hash
  end

这些需要公开。

答案 1 :(得分:18)

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

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

def state
  self.instance_variables.map { |variable| self.instance_variable_get variable }
end

答案 2 :(得分:1)

通常使用==运算符。

def == (other)
  if other.class == self.class
    @name == other.name && @num_stripes == other.num_stripes
  else
    false
  end
end