11

以下のコード スニペットで foo がその定義を置き換えるのはなぜですか?

def foo
  def foo
    1
  end
end

初めてfooゼロです

foo
=> nil

foo.foo
=> 1

fooもう一度電話すると:

foo
=> 1

ご覧のとおり、fooもう nil ではありません。誰かが私にこれを説明できますか?ありがとう。

4

6 に答える 6

7
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

于 2012-12-06T16:35:31.867 に答える
1

この効果が必要な場合は、お試しください

def foo
  foo = proc {
    1
  }
end

メソッドはdef新しい. selfすべてのメソッドは にバインドされてselfmainます。この場合は、Ruby インタープリターによって読み込まれたすべてのファイルに対してインスタンス化される Object.new です。クラスの中にはクラスselfがあり、インスタンス メソッドを取得します。

于 2012-12-06T16:49:12.993 に答える
1

メソッド定義は読み取り時に解析されますが、呼び出されるまで実行されません。最初の を実行fooすると、最も外側fooが実行され、次のように定義Object#fooされます。

def foo
  1
end

nilメソッドを定義した操作の戻り値として返されます。それ以降、 を呼び出すfooと、新しく定義されたfooが実行され、返されます

1
于 2012-12-06T16:49:36.290 に答える
0

最初に呼び出すfooとメソッドが返さfooれ、もう一度呼び出すと1fooが返されます。

于 2012-12-06T16:39:03.833 に答える
0

rubyのネストされたメソッド定義は混乱を招きます。

それらは実際には再定義です!

何が起こるかというと、両方の定義が最も外側のコンテキストに適用されます。つまり、両方の定義でsame(!)メソッドfooが定義されています。外部定義はファイルの読み取り時に解釈されますが、内部定義は外部メソッドが初めて呼び出されたときにのみ解釈されます。その後、初期定義が置き換えられます。

このコードを考えると

def foo
  def foo
    1
  end
end

これを見ていきましょう:

  1. ファイルをロードするとき、グローバルメソッドfooはbodyで定義されdef foo; 1; endます。
  2. foo()このグローバルメソッドを呼び出すと、実行され、本体を使用してグローバルメソッドが再定義 され、メソッドの定義には戻り値がないため、戻ります。foo1nil

  3. グローバルメソッドを呼び出すと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

ご覧のとおり、ネストされた定義は実際には再定義です。

于 2012-12-07T09:35:22.583 に答える
0

def個人的には、クラスの内部を定義するのは非常に奇妙だといつも思っていました。シングルトンで定義する方が賢明だと思います。たとえばdef self.foo、クラス レベルではなくインスタンス レベルで呼び出されるため、 と同等です。

それか、定義されているメソッドからのみ呼び出すことができますが、ラムダがあるため、それほど有用ではないかもしれません。

ただし、1 つ確かなことは、実際にこれを目にすることはほとんどないということです。

于 2012-12-09T17:39:44.283 に答える