Закрытие не работает - PullRequest
       0

Закрытие не работает

17 голосов
/ 18 февраля 2010

Если блок является замыканием, почему этот код не работает и как заставить его работать?

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>

Ответы [ 2 ]

26 голосов
/ 18 февраля 2010

Блоки являются замыканиями, и 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!
5 голосов
/ 18 февраля 2010

Если вы определяете класс динамически, вы можете изменить его, как вам нравится:

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!"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...