Закрытие не работает
Если блок является закрытием, почему этот код не работает и как заставить его работать?
def R(arg)
Class.new do
def foo
puts arg
end
end
end
class A < R("Hello!")
end
A.new.foo #throws undefined local variable or method `arg' for #<A:0x2840538>
Ответы
Ответ 1
Блоки замыкания и arg
действительно доступны внутри блока Class.new
. Он просто недоступен внутри метода foo
, потому что def
запускает новую область. Если вы замените def
на define_method
, который принимает блок, вы увидите нужный результат:
def R(arg)
Class.new do
define_method(:foo) do
puts arg
end
end
end
class A < R("Hello!")
end
A.new.foo # Prints: Hello!
Ответ 2
Если вы определяете класс динамически, вы можете изменить его по своему усмотрению:
def R(arg)
c = Class.new
# Send the block through as a closure, not as an inline method
# definition which interprets variables always as local to the block.
c.send(:define_method, :foo) do
arg
end
c
end
class A < R("Hello!")
end
puts A.new.foo.inspect
# => "Hello!"