2012-01-06 9 views
0

最後のyielderがnoブロックを与えた理由を説明することはできますか?yieldを指定して再定義されたメソッドは、ブロックが指定されていない

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:「で `ブロック内:30:いいえブロック与え(収量)(LocalJumpError)
をtest.rbから`にあなたはアウト@@ FOOを定義する場合は、モッズ・インスタンスを必要としない

:「

+0

これは 'define_method'の' instance_eval'の使用と関係しています。なぜなら 'class_eval'と文字列を使って古風なやり方ではうまく動作し、' instance_eval'は同じエラーが発生するからです。それでもまだ見えません:/ –

答えて

3

短い紹介側面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 
    define_method(:yielder) do 
    yield "new hello" 
    end 
end 

foo = Foo.new 
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 

これは同じです

はじめに。

そして今、あなたが望むものが正しいかどうかわかりません(そして、ルビーが正しいと理解すれば)) 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?でいくつかの小切手をお勧めします。

+0

'define_method'を送信すると、同じ暗黙のブロックメソッドのシグネチャが許可されません。 –

+0

実世界で使用するには、何度か失敗する方法が必要です。したがって、この質問は、非常に精巧な答えをいただきありがとうございます。 – patrick

+0

ああ、これもrspecのためにこれを台無しにする、私はこのケースはrspec maintainserのために面白いと思う、私はあなたの良い例で問題としてこれをファイルします。私もここにリンクを張ってルビー自体に問題を提出しました。 – patrick

関連する問題