2012-12-21 30 views
7

爲了回答這個問題:How can I make the set difference insensitive to case?,我嘗試使用集合和字符串,嘗試設置字符串不區分大小寫。但由於某種原因,當我重新打開String類時,我沒有任何自定義方法在向字符串添加字符串時被調用。在下面的代碼中,我看不到任何輸出,但我期望至少有一個我重載的操作符被調用。爲什麼是這樣?一組字符串並重新打開字符串

編輯:如果我創建一個自定義類,比如說,String2,我定義了一個哈希方法等,這些方法確實會在我將對象添加到集合時調用。爲什麼不是絃樂?

require 'set' 

class String 
    alias :compare_orig :<=> 
    def <=> v 
    p '<=>' 
    downcase.compare_orig v.downcase 
    end 

    alias :eql_orig :eql? 
    def eql? v 
    p 'eql?' 
    eql_orig v 
    end 

    alias :hash_orig :hash 
    def hash 
    p 'hash' 
    downcase.hash_orig 
    end 
end 

Set.new << 'a' 

回答

4

縱觀source codeSet,它使用一個簡單的哈希存儲:

def add(o) 
    @hash[o] = true 
    self 
end 

所以看起來你需要做的,而不是開什麼String是開放Set。我沒有測試過這一點,但它應該給你正確的觀念:

class MySet < Set 
    def add(o) 
    if o.is_a?(String) 
     @hash[o.downcase] = true 
    else 
     @hash[o] = true 
    end 
    self 
    end 
end 

編輯

正如在評論中指出,這可以在一個更簡單的方式來實現:

class MySet < Set 
    def add(o) 
    super(o.is_a?(String) ? o.downcase : o) 
    end 
end 
+1

一個簡單的'超級(o.is_a?(String)?o.downcase:o)'可能是一個更好的主意。 –

+0

謝謝。那是有效的,是的。如果我創建一個自定義類,比如說String2,我在其中定義了一個哈希方法等,當我將該對象添加到集合時,這些方法確實會被調用。爲什麼? (我編輯了我的問題)。 – akonsu

+0

Ruby源代碼(https://github.com/ruby/ruby/blob/trunk/hash.c#L1195)可能會提供一些線索。它看起來像'字符串'在MRI中被視爲散列鍵。 – Luke