2016-03-15 161 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