以下のコード スニペットで foo がその定義を置き換えるのはなぜですか?
def foo
def foo
1
end
end
初めてfoo
ゼロです
foo
=> nil
foo.foo
=> 1
foo
もう一度電話すると:
foo
=> 1
ご覧のとおり、foo
もう nil ではありません。誰かが私にこれを説明できますか?ありがとう。
以下のコード スニペットで foo がその定義を置き換えるのはなぜですか?
def foo
def foo
1
end
end
初めてfoo
ゼロです
foo
=> nil
foo.foo
=> 1
foo
もう一度電話すると:
foo
=> 1
ご覧のとおり、foo
もう nil ではありません。誰かが私にこれを説明できますか?ありがとう。
def foo
p "about to redef foo"
def foo
1
end
end
foo
"about to redef foo"
=> nil
foo
=> 1
また、を呼び出すとfoo.foo
、内部foo
メソッドにアクセスしようとしているように見えますが、そのようには機能しません。メソッドfoo
は実際にはで定義されてObject
いるため、実際にはを呼び出しています1.foo
。
この効果が必要な場合は、お試しください
def foo
foo = proc {
1
}
end
メソッドはdef
新しい. self
すべてのメソッドは にバインドされてself
いmain
ます。この場合は、Ruby インタープリターによって読み込まれたすべてのファイルに対してインスタンス化される Object.new です。クラスの中にはクラスself
があり、インスタンス メソッドを取得します。
メソッド定義は読み取り時に解析されますが、呼び出されるまで実行されません。最初の を実行foo
すると、最も外側foo
が実行され、次のように定義Object#foo
されます。
def foo
1
end
nil
メソッドを定義した操作の戻り値として返されます。それ以降、 を呼び出すfoo
と、新しく定義されたfoo
が実行され、返されます
1
最初に呼び出すfoo
とメソッドが返さfoo
れ、もう一度呼び出すと1foo
が返されます。
rubyのネストされたメソッド定義は混乱を招きます。
それらは実際には再定義です!
何が起こるかというと、両方の定義が最も外側のコンテキストに適用されます。つまり、両方の定義でsame(!)メソッドfooが定義されています。外部定義はファイルの読み取り時に解釈されますが、内部定義は外部メソッドが初めて呼び出されたときにのみ解釈されます。その後、初期定義が置き換えられます。
このコードを考えると
def foo
def foo
1
end
end
これを見ていきましょう:
foo
はbodyで定義されdef foo; 1; end
ます。foo()
このグローバルメソッドを呼び出すと、実行され、本体を使用してグローバルメソッドが再定義 され、メソッドの定義には戻り値がないため、戻ります。foo
1
nil
グローバルメソッドを呼び出すとfoo().foo()
、が実行されて戻り1
、グローバルメソッドが再度実行されて、1
再び戻ります。
ここで混乱するのは、a)ネストされたメソッド定義が両方とも同じ外部スコープに適用されることとb)グローバルメソッドを任意のオブジェクトで呼び出すことができることの2つです。
ネストされた定義が実際にどのように再定義されるかを示す別の例を次に示します。
class A
def m(arg=nil)
def m; 42; end if arg
23
end
end
これが何が起こるかです
a = A.new
a.m # => 23
a.m # => 23
a.m(:magic) # => 23
a.m # => 42
a.m # => 42
ご覧のとおり、ネストされた定義は実際には再定義です。
def
個人的には、クラスの内部を定義するのは非常に奇妙だといつも思っていました。シングルトンで定義する方が賢明だと思います。たとえばdef self.foo
、クラス レベルではなくインスタンス レベルで呼び出されるため、 と同等です。
それか、定義されているメソッドからのみ呼び出すことができますが、ラムダがあるため、それほど有用ではないかもしれません。
ただし、1 つ確かなことは、実際にこれを目にすることはほとんどないということです。