2015-05-27 69 views
1

我試圖使用ruby的forwardable module來使一個類中的某些變量可以被另一個類訪問。但是我在做這件事時遇到了一些麻煩。指定可轉發的類

看來,我能「前進」的self(代碼第一位)內的一些變數,但是我無法一類(代碼第二位)內提出了一些變量

以下工作原理:

require 'forwardable' 
module ModuleName 
    # 
    class << self 
    attr_accessor :config 
    def run 
     @config = {hey: 'hi', jay: 'ji'} 
     puts "1) Config = #{config}" 
    end 
    end 

    # 
    class Start 
    extend Forwardable 
    def_delegators ModuleName, :config 
    def run 
     puts "2) Config = #{config}" 
    end 
    end 
end 


ModuleName.run 
(ModuleName::Start.new).run 

#=> 1) Config = {:hey=>"hi", :jay=>"ji"} 
#=> 2) Config = {:hey=>"hi", :jay=>"ji"} 

但這並不

require 'forwardable' 
module ModuleName 
    # 
    class Data 
    attr_accessor :config 
    def run 
     @config = {hey: 'hi', jay: 'ji'} 
     puts "1) Config = #{config}" 
    end 
    end 

    # 
    class Start 
    extend Forwardable 
    def_delegators ModuleName::Data, :config 
    def run 
     puts "2) Config = #{config}" 
    end 
    end 
end 


(ModuleName::Data.new).run 
(ModuleName::Start.new).run 

#=> 1) Config = {:hey=>"hi", :jay=>"ji"} 
#=> /Users/ismailm/Desktop/ex.rb:17:in `run': undefined method `config' for ModuleName::Data:Class (NoMethodError) 

你能在固定的這部分代碼幫助...

+1

不應該是'def_delegators ModuleName :: Data,:config'(因爲你的班級不只是自己現在) – Tensibai

+0

@Tensibai是的你是對的,那就是我試過的(我把它複製錯了)..但它不起作用。請參閱上面的更新代碼 –

+0

由於「ModuleName :: Data.run」不存在,因此無法將':run'委託給'ModuleName :: Data'。你正在尋找定義'ModuleName :: Data.run'還是將調用委託給'ModuleName :: Data'的實例?通常在委派的情況下,你希望有一些動態的委託給 - 直接委派給單例方法是不常見的(因爲你已經有其他機制在代碼中建立靜態鏈接) –

回答

2

通常,當您在兩個類之間委派時,一個對象包含另一個對象的實例。您致電(ModuleName::Data.new).run的事實意味着,我認爲就是你正在嘗試做的,但不知何故失蹤的事實,你需要包含的類的實例保存在某個地方,以便接收呼叫:config

這你的第二個代碼段的變化是接近我希望在一個委派方案看:

require 'forwardable' 
module ModuleName 
    # 
    class Data 
    attr_accessor :config 

    def initialize 
     @config = {hey: 'hi', jay: 'ji'} 
    end 

    def run 
     puts "1) Config = #{config}" 
    end 
    end 

    # 
    class Start 
    extend Forwardable 

    def initialize data_obj = Data.new() 
     @data = data_obj 
    end 

    def_delegators :@data, :config 

    def run 
     puts "2) Config = #{config}" 
    end 
    end 
end 


(ModuleName::Data.new).run 
(ModuleName::Start.new).run 

我爲了顯示一個共同的模式,這裏不使用改變了構造函數ModuleName::Start。也就是說,你經常傳入包裝對象,或者更常見的是允許你構造一個新對象並將其分配給你想要委派給的實例變量的參數。

一個較小的相關更改:在您的原始代碼中,@config的值僅通過調用:run進行設置,因此直接指派給:config將不會讀取您期望的測試值。它在第一個版本中起作用,因爲@config在模塊上第一次調用run時被設置,然後在第二個委託調用中作爲單例方法全局讀取。我已經通過將其設置在Data的構造函數中來解決此問題,但是當然,在您委派的實例上設置值爲@config的任何內容都可以工作。