使用yield重新定义的方法不会产生任何阻塞

时间:2012-01-06 21:00:37

标签: ruby exception yield

有人可以解释为什么最后一个yielder会抛出一个无阻挡?

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
   yield "new hello"
end

Mod.foo.yielder do |hello|
  puts hello
end

给出:

  

您好
      test.rb:27:在`block in'中:没有给出块(yield)(LocalJumpError)
          来自test.rb:30:在''

1 个答案:

答案 0 :(得分:3)

简短介绍:

如果您在initialize之外定义@@ foo,则不需要Mod-instance。

您不需要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?进行一些检查。