2010-03-27 14 views
5

下面是一些示例代碼:Ruby的數組是如何實現的比較元素的平等?

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如何。|比較平等?

回答

6

Array#|使用hashs實現。因此,爲了使你的類型,以及與它(如包含HashMap和hashsets以及)工作,你就必須實現eql?(你沒有)和hash(你沒有)。定義哈希有意義的最直接的方法是返回c.hash

+0

只是爲了確認 - Ruby的Array#散列方法是否保證值相等當且僅當數組內容相等? – 2011-12-23 23:23:17

+0

@EricWalker號它保證兩個陣列hashs相等如果(但不是僅當)兩個陣列包含具有以相同的順序相同的散列值的元素。然而,這與這個問題無關,因爲這裏只對元素調用hash,而不是在數組本身。 – sepp2k 2011-12-23 23:27:51

1

Ruby的Array類是用C實現的,從我可以告訴,使用自定義的哈希表中|比較對象時要檢查是否相等。如果你想修改這種行爲,你必須編寫自己的版本,使用你選擇的相等性檢查。

要查看完整的Ruby實現的Array#|的:click here,搜索 「rb_ary_or(VALUE ary1, VALUE ary2)

0

紅寶石調用散列函數,他們正在返回不同的值,因爲它們仍然只是返回默認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>]