2013-01-06 37 views
4

我需要一個類似哈希的類,雖然不一定與所有的哈希方法。我已經讀過,將類核心類如Hash進行子類化並不是一個好主意。不管這是否屬實,做這種事情的最佳做法是什麼?子類核心Ruby類如哈希

# (a) subclass Hash, add new methods and instance variables 
class Book < Hash 
    def reindex 
    @index = ..... 
    end 
end 

# (b) create a new class from scratch, containing a hash, 
# and define needed methods for the contained hash 
class Book 
    def initialize(hash) 
    @data = hash 
    end 
    def []=(k,v) 
    @data[k] = v 
    end 
    # etc.... 
    def reindex 
    @index = .... 
    end 

# (c) like (b) but using method_missing 

# (d) like (b) but using delegation 

我意識到Ruby有完成既定任務的方法不止一種,但是否有任何一般規則,其中上述方法是比較簡單的情況下最好?

+2

當你只需要一些方法,我朝成分往往與委託。 –

+1

爲什麼你不能使用哈希?出了什麼問題?當您想要添加或更改方法時使用子類化,而不是在您想要刪除它們時使用。 – sawa

+0

@sawa,也許我不清楚。我確實想添加或更改方法。我的例子添加了「reindex」方法。 –

回答

10

如果我完全不希望哈希類對象具有某些哈希方法,那麼我會將該對象包裝在我自己的類中,只公開我想要的方法(您的選項b)。

如果我希望它保持並增加了一些行爲,其真正的散列的行爲,我會在一個模塊中添加行爲哈希對象本身,而不是修改核心哈希類:

module SpecialHash 
    def reindex 
    # method def 
    end 
end 

my_hash = {} 
my_hash.extend(SpecialHash) 
my_hash.reindex #now is defined on my hash 

最常見的,其中一個選項可以幫助我。

一般來說,我傾向於使用模塊來擴展類行爲而不是類繼承,因爲我認爲它是一種更清潔和更輕量級的方法。創建一個新班級總是讓我感覺我正在爲我的領域模型添加一個新的「事物」。這很好,正是你想在無數場景中做的事情,但是當你不需要去那麼遠的時候,Ruby的mixin功能爲你提供了一個非常好的選擇。

我將處理創建類的主要時間是如果我想跟蹤的對象中有一些額外的狀態。如果我的添加不是關於擴展對象的狀態,而是擴展它的行爲,那麼我幾乎總是會開始通過使用模塊將該行爲混合到該類的現有實例中。

另一個回答這類問題也帶來了值得牢記,以及其他一些觀點: ruby inheritance vs mixins

+0

我同意,但在他的情況下,選項(b)更好。他只想公開一小部分「哈希」方法並添加新方法。 – agarie

+0

實際上,我對是否要包含所有哈希方法的一般情況感興趣。正如現在所發生的一樣,讓他們都可用是很好的。但是,爲了解決Pete的解決方案,爲什麼將模塊添加到對象而不是簡單地繼承Hash? 「Book Book

+0

對不起,爲了讓我更深入地瞭解「爲什麼」,我選擇了在這種情況下做的選擇,試圖擴展我的答案。希望能幫助到你! – Pete