2

Ruby のメソッド内でメソッドを定義して実験することにし、次のように書きました。

def foo
  def bar
    puts "hello"
  end
  bar
end

これを定義して実行したfooところ、期待どおりに「こんにちは」が出力されました。しかし、私は試しfoo.barてみました - 「こんにちは」を2回出力しました。なんで?

4

3 に答える 3

4

foo.bar等しいので、含むfoo().bar()最初に呼び出すので、ここで 1 回実行され、次にもう一度実行されます。最後に2 回呼び出されます。foobarbarbar

def foo
  puts 'foo called'
  def bar
    puts 'bar called'
    puts "hello"
  end
  bar
end
foo.bar
#=> foo called
#=> bar called
#=> hello
#=> bar called
#=> hello

私が理解していないのは、これは結果foonil呼び出されることを意味するということbarです。

>> nil.bar
#=> hello

そんなことがあるものか ?

編集:いくつかの回答で説明されているように、ネストされたメソッドはクラススコープに含まれているため、バーがfooの内側または外側で宣言されていても違いはありません。

Ruby2.0から変わる可能性もあるとマッツさんも言ってた

彼が書いた例は次のとおりです。

class Foo
  def foo
    def bar
      #omited
    end
    bar # can be called
  end

  def quux
    bar # cannot be called
  end
end

edit-Ruby2.0 : 最終的に実装されませんでした。だからそれは同じままです。

于 2012-09-21T07:06:43.430 に答える
2

Ruby には、あまり注目されない隠し変数があります。それが何と呼ばれているかはわかりませんが、私はそれを現在のクラスと呼んでいます。この変数は、def

に入るfooと、この変数は変更されず、同じクラスにとどまります。したがって、foo の内部で別のメソッドを定義すると、そのメソッドは foo が定義されたのと同じクラスで定義されます。

この場合、最上位オブジェクトである main に foo を定義しています。Main の現在のクラス変数は object に設定されているため、ここで定義したメソッドはすべてのオブジェクト内で使用できます。

最後に行うことは bar の結果を返すことであり、bar は nil を返す (b/c puts は nil を返す) ため、foo.baris nil.bar. また、Object に bar を定義したので、nil でもこのメソッドを継承します。

興味深いのは、バーが公開されていることです。foo は main で定義されており、main はそのスコープを private に設定しているため、bar も private であると予想していましたが、別のスコープに移動すると、その状態は失われなければならないと思います。

于 2012-09-21T07:27:33.667 に答える
1

入れるつもりだったのclass foo?foo.bar を呼び出すと、関数 foo が呼び出され、次に関数 bar が呼び出されるようです。呼び出すnil.barと「hello」も出力されます。

于 2012-09-21T07:05:55.160 に答える