我试图在Ruby中使用元编程来创建类:Dynamically define named classes in Ruby。一切进展顺利,除了在Class.new
区块中似乎无法引用奇怪的参考方法参数。
我有这个
class A; end
module B
def self.class_with_method(class_name, method_return)
klass = Class.new(A) do
def example
method_return
end
end
B.const_set class_name, klass
end
end
但是当我有上述内容然后用
进行测试时B.class_with_method 'ExampleClass', 23
B::ExampleClass.new.example
给我
未定义的局部变量或方法`method_return' for#< B :: ExampleClass:0x00007ff1d7130d00> (NameError)
这很奇怪,因为如果我要做的话
def add_number(number)
[1, 2, 3, 4].map {|i| i + number}
end
add_number(2)
# => [3, 4, 5, 6]
很明显,块可以采用方法参数。
有没有办法在块中将method_return
传递给def example
?
答案 0 :(得分:1)
由于method_return
是一个变量,除非您在另一个上下文中使用它,否则无法将其传播到example
方法。您可以在类级变量中捕获它:
klass = Class.new(A) do
@@method_return = method_return
def example
@@method_return
end
end
您还可以动态定义方法,以便块捕获method_return
变量作为闭包:
klass = Class.new(A) do
define_method(:example) do
method_return
end
end
使用def example
时,块范围会发生变化并变得完全不同。
答案 1 :(得分:1)
这根本不奇怪,它是方法定义的常规行为:
class A
x = 3
def foo
x
end
end
A.new.foo # NameError: undefined local variable or method `x'
方法定义不会从外部范围捕获局部变量。这通常很好:通常你不希望方法的结果依赖于定义时存在的一些随机状态,你希望它依赖于你调用它的对象!
当然例外是你进行元编程。在这种情况下,捕获局部变量非常有用,因此您显式使用您在其他地方使用的相同机制来捕获它们:块。
define_method :example do
method_return
end
答案 2 :(得分:0)
def
结构缩小了范围。局部变量无法超越这一点。要做你想做的事,请改用define_method
。