这是一些解释我遇到的问题的测试代码。 Child类调用Parent类的方法。 Parent的一个方法在Parent上定义了一个名为foo
的新方法。在定义foo
之后,尝试从Child类调用它,但上下文完全不同(我只能访问Child的实例变量,而不是Parent的)。
我在这里猜测这与Ruby的闭包有关。当我拨打 编辑:我尝试使用lambda和proc,但它没有改变任何内容。define_method
时,我应该使用除了块之外的东西吗?
class Parent
@foo = 'foo'
def self.existing_method
puts "Calling existing_method, @foo is #{@foo}"
end
def self.define_new_method
self.class.send :define_method, :foo do
context = methods.include?('bar') ? 'child' : 'parent'
puts "Context is #{context}, @foo is #{@foo.inspect}"
end
end
end
class Child
@foo = 'childfoo'
def self.method_missing(*args, &block)
Parent.send args.shift, *args, &block
end
def self.bar
end
end
Child.existing_method # Calling existing_method, @foo is foo
Child.define_new_method
Child.foo # Context is child, @foo is "childfoo"
# (in Ruby 1.9, the context is parent, but
# @foo is still "childfoo")
Parent.foo # Context is parent, @foo is "foo"
这个结果不是我想要的。 Child.foo
的回复应与Parent.foo
的回复相同。
提前致谢!
答案 0 :(得分:0)
经过大量的挖掘,这就是我想到的。
self.class.define_method
实际上定义了Object
的实例方法。这意味着所有收到了新方法,这是明显的上下文转换的原因(Child.foo
实际上是在调用Child.foo
而不是Parent.foo
)。糟糕。self
,它是class << self; self; end
(是的,我没有得到它其一)。这里简要提到了代码:http://blog.jayfields.com/2007/10/ruby-defining-class-methods.html class Parent
@foo = 'foo'
def self.existing_method
puts "Calling existing_method, @foo is #{@foo}"
end
def self.define_new_method
inst = class << self; self; end # Do not understand this...
inst.send :define_method, :foo do
context = methods.include?(:bar) ? 'child' : 'parent'
puts "Context is #{context}, @foo is #{@foo.inspect}"
end
end
end
class Child
@foo = 'childfoo'
def self.method_missing(*args, &block)
return unless args.length > 0
Parent.send args.shift, *args, &block
end
def self.bar
end
end
Child.existing_method # Calling existing_method, @foo is foo
Child.define_new_method
Child.foo # Context is parent, @foo is "foo"
Parent.foo # Context is parent, @foo is "foo"
答案 1 :(得分:0)
这很有趣;我认为Yehuda Katz今天的帖子解释了完全你想要什么:http://yehudakatz.com/2010/02/15/abstractqueryfactoryfactories-and-alias_method_chain-the-ruby-way/
编辑:好的 - 这不是“你要求的东西”,第二个想法,因为它不是元编程,但它最有可能更接近你想做的事情。至于你的具体答案,我会看一下代码。
答案 2 :(得分:0)
在Ruby 1.9x中,
&#39;方法&#39;方法返回Symbol(method name) Array
。
因此使用respond_to
方法:
context = respond_to?(:bar) ? 'child' : 'parent'