在Java和C#等语言中,如果要覆盖相等运算符,则必须覆盖哈希方法。
每当a.equals(b),则a.hashCode()必须与b.hashCode()相同
据我所知,这些语言中的一些内部数据结构依赖于上述条件,以便正常运行。
我想知道Ruby中是否也是如此。覆盖hash
运算符时,是否需要覆盖对象的==
方法?我听说在覆盖eql?
时需要覆盖==
。这些声明背后的原因是什么,以及如果你不会覆盖这些声明会发生什么?
答案 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?
方法。