我在SO上找到了这个基于'tee'实现的整洁的委托人:
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)
我得到它定义方法write / close但是@targets在这一点上甚至没有被定义,因为.to(别名为new)还没有被调用所以我假设@targets是nil。
任何人都可以解释一下这段代码的工作方式吗? ruby甚至没有尝试访问/解析@targets,直到尝试调用有问题的方法,记录器在实例化后会被调用吗?
答案 0 :(得分: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
方法(与之前相同的实例!)并且它运行正常。
最后一个示例显示了定义方法如何不运行它,或者要求它在运行时甚至可以工作。每次调用时都会动态评估它(并且仅在那时)。