2012-04-30 10 views
0

我在Ruby(1.9.3)中編寫了一小段代碼,並使用了一對簡單的「枚舉類」類,它們定義了一些常量,其中常量集合爲const_set而這些常量的某些行爲(例如類可能有常數MONTUE ...和天:: MON.succ應該評估爲TUE)。使用Class.new創建的類中的常量

我非常喜歡這些課程。然而,當越來越多我的代碼,我有時需要添加更多的人,我不喜歡有五個以上的類共享源代碼的99%,如的想法:

class Days 
    NAMES = %w(MON TUE ...) 
    INSTANCES = [] 

    def initialize(num) 
    @num = num 
    end 

    # An example operation 
    def +(n) 
    INSTANCES[(@num + n) % INSTANCES.length] 
    end 

    # Another example operation 
    def succ 
    self + 1 
    end 

    def to_s 
    NAMES[@num] 
    end 

    NAMES.each_with_index do |name, idx| 
    instance = new(idx) 
    INSTANCES[idx] = instance 
    const_set name, instance 
    end 
end 

class Months 
    NAMES = %w(JAN FEB ...) 
    ... 
end 

我想知道如果Ruby的元編程功能可以用來生成這些類。但是,我有一個困難時期創造名字INSTANCES和 「枚舉爲」 常數(例如MONTUE,...)。 作爲const_set類的一個類的方法,在該代碼它的上下文是分別(的的值)。

創建一個工廠方法時,我不得不做這樣的事情:

def enum_new(names_array) 
    Class.new do 
    const_set "NAMES" [] 
    names_array.each_with_index do |name, idx| 
     NAMES[idx] = name 
    end 
    ... 
    end 
end 
Days = enum_new(%w| MON TUE ... |) 
Months = enum_new(%w| JAN FEB ... |) 

,但是這不會工作(至少,不會像我希望它),因爲const_set韓元「T中的類的名字是神奇集的上下文中調用(即),但顯然在類的上下文中因此,不僅實例方法無法訪問它,而且每次調用enum_new都會使用新的名稱數組作爲參數調用它。使用類變量時會出現類似的問題,因爲它們將在用該方法生成的任何類之間共享(因爲它們將變成的類變量,我猜)。

有什麼方法來創建與Class.new生成的類的常量,獲得這樣的類相同的一切,原來類,而不必污染我的代碼幾乎相同的班?

感謝您的關注和耐心! :)

+0

能否請你在你與你的省略號發出的代碼填? – Linuxios

+0

我完成了第一個類的代碼,並添加了兩個示例操作來顯示我需要如何訪問實例方法中的常量。當然,通過用const_set創建的常量來訪問實例。 –

回答

1

是的。做你的初始化在class_exec塊,在其中您可以將您的姓名數據並在self指的是正確的類:

theClass=Class.new 
theClass.class_exec(names) do |names| 
    #initialize constants here... 
end 
+0

謝謝,這實際上給我帶來了一些正是我想要的工作代碼。然而,我注意到,如果我在與** class_exec **相關的塊中'const_set'NAME',value',我必須在同一個塊中引用** NAME **作爲'self :: NAME',並且作爲'self.class :: NAME'在與** Class.new **相關的塊中。是否有一個特定的原因,它只能顯式引用** self **?爲什麼與** class_exec **關聯的塊中的常量名稱引用全局常量? –

+0

他們沒有。 'class_exec'可以被認爲是普通類定義的'class'和'end'之間的地方。至於你必須使用'self'這一事實,那是因爲直到你把它賦給一個常量,這個類實際上是未命名的,並且必須從'self'對象或*變量*'theClass'訪問。一旦你將它分配給一個常量(例如'Days'),就可以用'Days :: MON'訪問事物。 – Linuxios

+0

我的意思是代碼'NAMES = ['nothing']; A類; NAMES = ['foo'];結束; A.class_exec {NAMES [0] ='bar'}; p NAMES [0]'打印_bar_。我們在一個已命名的類中使用'class_exec',但在相關的塊中使用的常量名稱指的是全局常量'NAMES',而不是'A'類中的那個;這是我沒有預料到的行爲:) –