2016-03-15 199 views
2

我發現這種基於委託整齊的SO「三通」的實現:實例變量

https://stackoverflow.com/a/6410202/2379703

,我很好奇的意思是@targets(實例變量)是指在上下文一類方法:

require 'logger' 

class MultiDelegator 
    def initialize(*targets) 
    @targets = targets 
    end 

    def self.delegate(*methods) 
    methods.each do |m| 
     define_method(m) do |*args| 
     @targets.map { |t| t.send(m, *args) } 
     end 
    end 
    self 
    end 

    class <<self 
    alias to new 
    end 
end 

log_file = File.open("debug.log", "a") 
log = Logger.new MultiDelegator.delegate(:write, :close).to(STDOUT, log_file) 

我得到它定義方法寫/接近,但@targets甚至沒有在自。要(化名到新)這個點定義還有待所謂的我假設@targets爲零。

任何人都可以解釋這個代碼的工作原理嗎?在嘗試調用有問題的方法之前,ruby是否甚至不嘗試訪問/解析@targets,在實例化之後它將由記錄器進行調用?

回答

1

在類上調用define_method方法來創建實例方法。在該方法中,self(和實例變量)是該類的實例。

例如:

class Foo 
    @bar = "CLASS" 
    def initialize 
    @bar = "INSTANCE" 
    end 
    def self.make_method 
    define_method :whee do 
     p @bar 
    end 
    end 
end 

begin 
    Foo.new.whee 
rescue NoMethodError=>e 
    puts e 
end 
    #=> undefined method `whee' for #<Foo:0x007fc0719794b8 @bar="INSTANCE"> 

Foo.make_method 
Foo.new.whee 
#=> "INSTANCE" 

這是正確的,你可以詢問從未被創建的實例變量,在任何時候:

class Bar 
    def who_dat 
    puts "@dat is #{@dat.inspect}" 
    end 
end 

Bar.new.who_dat 
#=> dat is nil 

同樣是其他方面真語言。只要在該方法的代碼是語法有效,它可以被定義,即使調用它會導致運行時錯誤:

class Jim 
    def say_stuff 
    stuff! 
    end 
end 
puts "Good so far!" 
#=> Good so far! 

j = Jim.new 
begin 
    j.say_stuff 
rescue Exception=>e 
    puts e 
end 
#=> undefined method `stuff!' for #<Jim:0x007f9c498852d8> 

# Let's add the method now, by re-opening the class 
class Jim # this is not a new class 
    def stuff! 
    puts "Hello, World!" 
    end 
end 

j.say_stuff 
#=> "Hello, World!" 

在上述我限定say_stuff方法,該方法在語法上是有效的,但是這調用一個不存在的方法。這是找到的。該方法已創建,但未調用。

然後我嘗試調用該方法,並導致一個錯誤(我們捕捉並處理乾淨)。

然後,我添加stuff!方法的類。現在我可以運行say_stuff方法(與之前的實例相同!),它工作得很好。

最後一個例子顯示瞭如何定義一個方法不運行它,或者要求它在運行時甚至可以工作。每次調用時都會動態評估(並且只在當時)。

+0

Ahh define_method定義了一個實例方法,儘管在類方法中被調用。我讀了更多,似乎在封面下使用了instance_eval,所以我看到@targets是如何調用實例的實例變量。 – jshort