比较Ruby中的对象等价

Ric*_*cky 6 ruby

我在这里做一个Ruby教程:http: //rubymonk.com/learning/books/4-ruby-primer-ascent/chapters/45-more-classes/lessons/105-equality_of_objects

它说当我重载==运算符时我也应该重载eql?方法和哈希方法,因为它们"更快".

但是,如果我用基本相同的方法重载所有三个,那么一个比另一个快?

Mar*_*une 13

在大多数情况下,==eql?具有相同的结果.在某些情况下,eql?==以下更严格:

42.0 == 42 # => true
42.0.eql?(42) # => false
Run Code Online (Sandbox Code Playgroud)

因此,如果你定义了==你可能也想要定义eql?(反之亦然).

选择Hash该类将用于eql?区分不同的键,而不是==.它可能是==,请注意,但eql?更清洁.

为了避免一直进行昂贵的调用eql?,计算哈希值时要求两个对象eql?必须具有相同的哈希值.存储该哈希值,这使得将来的查找非常容易:如果哈希码不匹配,那么值不是eql?......

因此,如果定义,必须hash以合理的方式定义eql?.

请注意,计算哈希值几乎总是比使用==或进行比较更昂贵eql?.但是,一旦计算了哈希值,检查哈希值是否匹配非常快.

因为散列通常涉及很多比较,所以对于每个键,相对昂贵的散列计算执行一次,然后对每次查找执行一次.想象一下有10个条目的哈希.hash在第一次查找完成之前,构建它将涉及10次调用.第一次查找将相对较快:一次调用hash,然后非常有效地比较哈希码(它实际上比这更快,因为它们被"索引").如果有匹配,必须仍然要打电话eql?以确保它是真正的匹配.实际上,两个不eql?具有相同散列的对象.唯一的保证是两个对象eql?必须具有相同的哈希值,但两个不同的对象也可以具有相同的哈希值.

如果您想使用Array相反的方法,则eql?每次查找可能需要10次调用.

对于它的价值,我不认为你链接到的Ruby引物尽可能清晰.它忽略了这样一个事实,即计算它hash可能是昂贵的,所以只有当它有意义时才会这样做,即当一个好的假设是每个元素将被多次比较时.此外,令人遗憾的是,eql?它提供的自定义示例==用于比较实例变量.理想情况下,它会使用eql?的一致性,以同样的方式,数组==,如果它的元素==和数组是eql?如果它的元素eql?.最后,它确实应该提到Struct哪个定义体面==,hasheql?为您.