你需要覆盖hash和eql吗?在Ruby中覆盖==运算符时?

时间:2016-07-11 17:21:18

标签: ruby oop

在Java和C#等语言中,如果要覆盖相等运算符,则必须覆盖哈希方法。

  

每当a.equals(b),则a.hashCode()必须与b.hashCode()相同

据我所知,这些语言中的一些内部数据结构依赖于上述条件,以便正常运行。

我想知道Ruby中是否也是如此。覆盖hash运算符时,是否需要覆盖对象的==方法?我听说在覆盖eql?时需要覆盖==。这些声明背后的原因是什么,以及如果你不会覆盖这些声明会发生什么?

2 个答案:

答案 0 :(得分:1)

不,您没有 需要 来覆盖eql?hash方法。

然而,正如tadman所提到的,你应该覆盖它们。你不知道eql是怎么回事?可能会被使用,如果你不覆盖哈希,那么如果你将对象用作哈希键,你会得到奇怪的结果。请参阅此blog post

说了这么多,你提出了一个有趣的观点:

  

在Java和C#中,您也必须覆盖哈希方法。

如果不覆盖哈希方法会发生什么?它会无法编译,还是一种糟糕的做法?

感觉就像Ruby一样,很少有这样的硬性规则和快速规则。我想知道与C#,Java和C ++等语言相比,Ruby是否有不同的范例。也许范式是不同的,因为Ruby是鸭子类型,没有单独的编译过程。

答案 1 :(得分:0)

Ruby有3个平等方法==eql?equal?。在基类Object类中,它们都是相同的,但对于更具体的类,它们提供了特定于类的语义。

他们比较的是依赖于实现该类的开发人员,但是,有一个约定。

== - 值比较

两个对象具有相同值时为真。

2.2.3 :011 > 5 == 5.0  
 => true 
2.2.3 :012 > 'test' == 'test'  
 => true 
2.2.3 :013 > { a: 10 } == { a: 10.0 }  
 => true 
2.2.3 :014 > :test == :test  
 => true 
2.2.3 :016 > ['a', :test, 10] == ['a', :test, 10.0]  
 => true

eql? - 值和类型比较

当两个对象具有相同的值并输入

时为真
2.2.3 :028 > 'test'.eql? 'test'  # Strings  
 => true 
2.2.3 :029 > 5.eql? 5  # Fixnums  
 => true 
2.2.3 :030 > 5.eql? 5.0  # Fixnum & Float  
 => false 
2.2.3 :032 > { a: 10 }.eql?({ a: 10 })  # Hash  
 => true 
2.2.3 :033 > { a: 10 }.eql?({ a: 10.0 })  
 => false

equal? - 参考比较

两个对象共享相同的内存引用时为True。永远不应该覆盖此方法。

2.2.3 :017 > 'test'.equal? 'test'  
 => false 
# Each string is an independent object even if they share content
2.2.3 :018 > :test.equal? :test  
 => true 
# Symbols share reference if they have the same content
2.2.3 :019 > 1.equal? 1  
 => true 
2.2.3 :020 > [].equal? []  
 => false 
2.2.3 :021 > a = 'test'  
 => "test" 
2.2.3 :022 > b = a    # b is a reference to the same object as a  
 => "test" 
2.2.3 :023 > b.equal? a  
 => true 

如果您只是覆盖了==,那么 需要来覆盖hash方法,但应该,以防万一调用eql?equal?方法。