Краткое введение:
Вам не нужен экземпляр Mod, если вы определяете @@ foo снаружи initialize
.
Вам не нужен класс Mod для решения проблемы:
class Foo
def yielder
p 2
yield "hello"
end
end
foo = Foo.new
foo.yielder do |hello|
puts hello
end
foo.class.send(:define_method,:yielder) do
p 1
yield "new hello"
end
foo.yielder do |hello|
puts hello
end
Вы можете снова сократить свой пример:
class Foo
end
foo = Foo.new
foo.class.send(:define_method,:yielder) do
yield "new hello"
end
foo.yielder do |hello|
puts hello
end
Это то же самое, что и
class Foo
define_method(:yielder) do
yield "new hello"
end
end
foo = Foo.new
foo.yielder do |hello|
puts hello
end
Конец введения.
А теперь я не уверен, правильно ли я понял, что вы хотите (и если я правильно понимаю, рубин правильно;))
define_method
принимает блок и использует его как тело метода.
Если новый метод должен получить блок самостоятельно, вы должны определить его в интерфейсе определения и вызвать его:
class Foo
define_method(:yielder) do | &prc |
prc.call("new hello")
end
end
foo = Foo.new
foo.yielder do |hello|
puts hello
end
Или та же логика в вашем примере:
class Foo
def yielder
yield "hello"
end
end
class Mod
def initialize
@@foo = Foo.new
end
def self.foo
@@foo
end
end
worker = Mod.new
Mod.foo.yielder do |hello|
puts hello
end
Mod.foo.class.send(:define_method,:yielder) do | &prc |
prc.call "new hello"
end
Mod.foo.yielder do |hello|
puts hello
end
Чтобы сделать код более устойчивым, я бы порекомендовал некоторые проверки с block_given?
.