以下是一些示例代码:
class Obj
attr :c, true
def == that
p '=='
that.c == self.c
end
def <=> that
p '<=>'
that.c <=> self.c
end
def equal? that
p 'equal?'
that.c.equal? self.c
end
def eql? that
p 'eql?'
that.c.eql? self.c
end
end
a = Obj.new
b = Obj.new
a.c = 1
b.c = 1
p [a] | [b]
它打印2个对象,但它应该打印1个对象。没有调用任何比较方法。 Array怎么样。|比较平等?
答案 0 :(得分:6)
Array#|
是使用哈希实现的。因此,为了使您的类型能够很好地与它一起使用(以及使用哈希映射和哈希集),您必须实现eql?
(您做过)和hash
(您没有)。有意义地定义哈希的最直接的方法是返回c.hash
。
答案 1 :(得分:1)
Ruby的Array类是用C实现的,据我所知,在比较|
中的对象时,使用自定义哈希表来检查是否相等。如果您想修改此行为,则必须编写自己的版本,使用您选择的相等检查。
要查看Ruby的Array#|
:click here的完整实现并搜索“rb_ary_or(VALUE ary1, VALUE ary2)
”
答案 2 :(得分:0)
Ruby正在调用哈希函数,并且它们返回不同的值,因为它们仍然只是返回默认的object_id。您将需要def hash
并返回一些反映您对Obj重要性的想法。
>> class Obj2 < Obj
>> def hash; t = super; p ['hash: ', t]; t; end
>> end
=> nil
>> x, y, x.c, y.c = Obj2.new, Obj2.new, 1, 1
=> [#<Obj2:0x100302568 @c=1>, #<Obj2:0x100302540 @c=1>, 1, 1]
>> p [x] | [y]
["hash: ", 2149061300]
["hash: ", 2149061280]
["hash: ", 2149061300]
["hash: ", 2149061280]
[#<Obj2:0x100302568 @c=1>, #<Obj2:0x100302540 @c=1>]