2010-07-14 80 views
1

如果我分別創建兩個具有相同內容的String實例,它們是相同的。默認情況下,自定義類不是這種情況(請參見下面的示例)。Ruby實例的唯一性

如果我有我自己的課程(Test下面),我有一個變量(@v下面),這是唯一的,即。兩個Test具有相同@v的實例應該被視爲相同,那麼我將如何去告訴Ruby這種情況?

考慮這個例子:

class Test 
    def initialize(v) 
    @v = v 
    end 
end 

a = {Test.new('a') => 1, Test.new('b') => 2} 

a.delete(Test.new('a')) 

p a 
# # Desired output: 
# => {#<Test:0x100124ef8 @v="b">=>2} 
+0

具有相同內容的兩個字符串實例不相同。 '「string」.equal?(「string」)'returns' false' – 2010-07-14 23:22:55

+0

啊,我的錯。我認爲他們是因爲'a = {'string'=>'一個字符串'}; a.delete('string')'起作用! – 2010-07-15 01:46:02

+0

@JP:我認爲散列有一個特殊情況,如果他們使用字符串作爲關鍵。 – 2010-07-15 01:55:23

回答

1

我發現了一個不同的方式來解決這個問題,通過跟蹤測試的所有實例的內部我可以返回預製的實例,而不是做一個新的,並告訴紅寶石他們是等價的:

class Test 
    def self.new(v) 
    begin 
     return @@instances[v] if @@instances[v] 
    rescue 
    end 

    new_test = self.allocate 
    new_test.instance_variable_set(:@v,v) 
    (@@instances ||= {})[v] = new_test 
    end 
end 

現在Test.new('a') == Test.new('a')Test.new('a') === Test.new('a') :)

1

您需要定義一個==方法,它定義了平等意味着你的類。在這種情況下,您需要:

class Test 
    def initialize(v) 
    @v = v 
    end 
    def ==(other) 
    @v == other.instance_variable_get(:@v) 
    end 
end 
+0

太棒了,謝謝!這肯定會起作用,但如果我在'a1 = Test上更改屬性。新('a')'也會在'a2 = Test.new('a')'上顯而易見嗎?我真的希望他們*是同一個對象,而不僅僅是等同。 – 2010-07-14 22:39:10

+0

糟糕,我說得太快了,並且在上面的示例中添加了'=='方法實際上並沒有給出所需的輸出 - 對不起! – 2010-07-14 22:40:49

1

您正在使用類Test的對象作爲散列的關鍵字。爲了,爲了正確地(並因此a.delete)的功能,你需要定義兩個方法中測試:Test#hashTest#eql?

來源:http://ruby-doc.org/core/classes/Hash.html

哈希使用key.eql?測試 等號的密鑰。如果您需要使用您自己的類的實例 作爲哈希密鑰, ,建議您同時定義 eql?和散列方法。散列 方法必須具有以下屬性: a.eql?(b)意味着a.hash == b.hash。

1

大部分的時間,對象需要具有可比性和/或哈希的組成成員變量,或者是原語(整數,字符串等),或者是本身可比/可拆分。在這些情況下,這個模塊:

module Hashable 

    include Comparable 

    def ==(other) 
    other.is_a?(self.class) && other.send(:parts) == parts 
    end 
    alias_method :eql?, :== 

    def hash 
    parts.hash 
    end 

end 

可以簡單地包含在你的班級,照顧所有的忙碌工作。所有你需要做的就是定義返回所有包含對象的狀態值的「零件」法:這種方法構建具有可比性(他們有

class Foo 

    include Hashable 

    def initialize(a, b) 
    @a = a 
    @b = b 
    end 

    private 

    def parts 
    [@a, @b] 
    end 

end 

對象<,< =,= =,> = ,>,!=和equ?),它們可以是散列鍵。