2013-04-18 58 views
1

我有一個我正在開發的gem。它是一個可執行文件,用於解析配置文件,然後實例化一些對象。其中一個對象然後實例化一些「處理程序」對象。我正在將配置文件解析爲一個數組,CONFIG,但其中的設置不能在任何其他對象中訪問。他們是在處理程序中需要的。當我嘗試使用它們時,變量不存在。在嵌套對象中訪問ruby變量

我知道這是一個可變範圍問題。但是我不確定我需要做什麼才能使這些在整個程序(包括子/嵌套對象)中可訪問,而不僅僅是最初的可執行文件。雖然程序中的每個對象都位於一個模塊中,但可執行文件中的操作不是。

回答

1

常量是全局的,但它們生活在它們被定義的名稱空間中。

如果您在主環境中定義了CONFIG,它將在根級別爲全局。如果您在類或模塊中定義它,則必須在該上下文之外以全名引用它。

例如:

class Foo 
    CONFIG = File.read(...) 
end 

CONFIG # => Error, not defined 
Foo::CONFIG # => Defined 

這是普遍不好的形式按名稱引用常量,這將違背正確的面向對象設計的糧食。因此,如果你定義了常量,它們應該只在內部使用,並且通過子類可以根據需要重新定義或修補的方法公開。

一個更好的例子:

class Foo 
    CONFIG = File.read(...) 

    def self.config 
    CONFIG 
    end 
end 

Foo.config # => Your configuration 

這個簡單的抽象,因爲一個子類可以重新定義你的配置是很重要的:

class Bar < Foo 
    def self.config 
    # ... Different implementation 
    end 
end 

Bar.config # => Different result 

更妙的是完全避免,只是lazy-常數根據需要加載東西:

class Foo 
    def self.config 
    @config ||= File.read(...) 
    end 
end 

Foo.config # => Your configuration 

常量是最好的東西s不會改變,如SEPARATOR = ':',在不破壞大量代碼的情況下重新配置它們是不可能或不實際的。

如果您有從外部源讀取的內容,它可能會根據配置或偏好而有所不同,那麼通常使用中介方法更方便。

+0

哇,這是一個很好的答案,並給了我很多關於事物範圍的見解。 Ruby是我第一次接觸任何面向對象的東西。在這種情況下,我將代碼中的「main」部分的配置加載到任何類的外部。我是否需要將配置移動到它自己的類中,還是在那種情況下還有其他一些「好」的方法來完成此操作? – Jericon

+0

在自己的類中配置它使測試變得更容易,所以這可能是一個好主意。當配置本身包含在一個整潔的結構中,而不是散佈在數十個獨立變量中時,這也很好。 – tadman