Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';这是在ruby中实现平等的正确方法_Ruby_Equality - Fatal编程技术网

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

什么';这是在ruby中实现平等的正确方法,ruby,equality,Ruby,Equality,对于简单的类似结构的类: class Tiger attr_accessor :name, :num_stripes end 正确实现相等的正确方法是什么,以确保==、==、eql?等正常工作,从而使类的实例在集合、哈希等中很好地发挥作用 编辑 另外,当您希望基于未在类外公开的状态进行比较时,实现相等的好方法是什么?例如: class Lady attr_accessor :name def initialize(age) @age = age end end 在这

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

class Tiger
  attr_accessor :name, :num_stripes
end
正确实现相等的正确方法是什么,以确保
==
==
eql?
等正常工作,从而使类的实例在集合、哈希等中很好地发挥作用

编辑

另外,当您希望基于未在类外公开的状态进行比较时,实现相等的好方法是什么?例如:

class Lady
  attr_accessor :name

  def initialize(age)
    @age = age
  end
end

在这里,我希望我的平等方法考虑到@age,但这位女士不会向客户透露她的年龄。在这种情况下,我必须使用实例变量get吗?

通常使用
=
操作符

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

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

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

这些必须是公共的。

要同时测试所有实例变量的相等性:

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

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

谢谢然而,我认为如果您只定义==的话,那么类的实例在哈希和集合中的行为就不会像预期的那样。而且,我/think/that==不应该检查类型相等性(就像您的示例所做的那样)。这就是eql?应该这样做。这可能是错误的。只有你改变了,行为才会改变,皮特。上次我选中的
true==true
(和
1+1==2
)仍然返回
true
…我非常喜欢这种通过将比较委托给状态数组来比较对象的技巧。不幸的是,这已经结束了我的工作head@kraftydevil这确实是不幸的。对此我很抱歉。像这样的类比较怎么样:
o.is\u a?(self.class)
?。我知道它的行为(后代),但我正在寻找最佳实践。@DonPaulie我不知道那里是否有最佳实践。我不太使用继承,所以我不必决定子类的实例是否应该等于其父类的实例。我会根据具体情况来考虑。这真的好得多,因为它可以确保你不会意外地漏掉任何变量。现在,自动使用每个实例变量可能会产生一些意想不到的后果,但我不确定,也不知道,直到有一天我感到惊讶。没错,您可以为这些特定情况添加可选参数,如“only”或“except”。