34

これは、元の SO の質問の続きです: Ruby ネームスペースに "::" の代わりに "module ..." を使用する

元のSOの質問では、ここに提示されたシナリオがありますが、私はまだ理解に苦しんでいます:

FOO = 123

module Foo
  FOO = 555
end

module Foo
  class Bar
    def baz
      puts FOO
    end
  end
end

class Foo::Bar
  def glorf
    puts FOO
  end
end

puts Foo::Bar.new.baz    # -> 555
puts Foo::Bar.new.glorf  # -> 123

最初の呼び出しが 555 を返す理由と、2 番目の呼び出しが 123 を返す理由を誰かが説明できますか?

4

4 に答える 4

36

module Somethingclass Somethingまたはの各出現は、def something新しいスコープへの「ゲートウェイ」と考えることができます。Ruby が参照されている名前の定義を検索するとき、最初に現在のスコープ (メソッド、クラス、またはモジュール) を検索し、そこに見つからない場合は、「ゲートウェイ」を含むそれぞれに戻って検索します。そこの範囲。

あなたの例では、メソッドbazは次のように定義されています

module Foo
  class Bar
    def baz
      puts FOO
    end
  end
end

の値を決定しようとするとFOO、最初にクラスBarがチェックされ、Bar含まれていないためFOO、検索は「<code>class Bar ゲートウェイ」を介してFoo、含まれるスコープであるモジュールに移動します。Fooには定数 (555) が含まれているFOOため、これが表示される結果です。

メソッドglorfは次のように定義されます。

class Foo::Bar
  def glorf
    puts FOO
  end
end

ここで「ゲートウェイ」はで、「ゲートウェイ」内に見つからないclass Foo::Bar場合は、モジュールを通過してトップ レベルに直行し、別の(123) が表示されます。FOOBarFooFOO

class Foo::Barusingが単一の「ゲートウェイ」を作成し、 のスコープをスキップする方法に注意してください。ただし、 2 つの別個の「ゲートウェイ」 Fooが開きます。</p>module Foo; class Bar ...

于 2013-03-03T17:02:01.057 に答える
6

うわー、素晴らしい質問。私が思いつくことができる最良の答えは、この場合、モジュールを使用して名前空間を定義していることです。

これをチェックしてください:

FOO = 123

module Foo
  FOO = 555
end

module Foo
  class Bar
    def baz
      puts FOO
    end

    def glorf3
      puts ::FOO
    end
  end
end

class Foo::Bar
  def glorf2
    puts Foo::FOO
  end

  def glorf
    puts FOO
  end
end

puts Foo::Bar.new.baz    # -> 555
puts Foo::Bar.new.glorf  # -> 123
puts Foo::Bar.new.glorf2  # -> 555
puts Foo::Bar.new.glorf3  # -> 123

だから私の考えは、あなたが定義するとき:

module Foo
  FOO = 555
end

FOOの名前空間で作成していますFoo。したがって、ここで使用する場合:

module Foo
  class Bar
    def baz
      puts FOO
    end
  end
end

Foo名前空間にいます。ただし、次の場所で参照する場合:

class Foo::Bar
  def glorf
    puts FOO
  end
end

FOOデフォルトの名前空間から来ています(で示されているように::FOO)。

于 2013-02-27T19:14:45.443 に答える
0

glorf は Foo クラスのメソッドです。=> [Foo, Module, Object, Kernel, BasicObject]

そのスコープ内 (つまり、デフォルト/メイン モジュール内) では、FOO に 123 が割り当てられます。

モジュール Foo は次のように定義されます

module Foo
  FOO = 555
  class Bar
    def baz
      puts FOO
    end
  end
end

ここで、メソッド baz はモジュール Foo のクラス Bar に属します=> [Bar, Foo, Object, Kernel, BasicObject]

そのスコープで FOO には 555 が割り当てられました

于 2013-03-04T08:06:44.827 に答える
0

最初の呼び出し:

puts Foo::Bar.new.baz    # -> 555

クラスFoo::Barのインスタンスのメソッドbazを呼び出した結果を出力します

Foo::Bar#bazの定義は、実際には FOO のクロージャーであることに注意してください。Ruby のスコープ ルールに従います。

  1. FOOFoo::Bar (インスタンスではなくクラス) スコープで検索されますが、見つかりません。
  2. FOOは、囲んでいるスコープFooで検索され(モジュール定義内にあるため)、そこに見つかります (555)

2 番目の呼び出し:

puts Foo::Bar.new.glorf  # -> 123

クラスFoo::Barのインスタンスのメソッドglorfを呼び出した結果を出力します

今回のFoo::Bar#glorf の定義もFOO のクロージャであることに注意してください。しかし、Ruby のスコープ規則に従うと、この時点でクローズされる値は次のように::FOO (トップ レベル スコープ FOO) であることがわかります。 :

  1. FOOFoo::Bar (インスタンスではなくクラス) 名前空間で検索されますが、見つかりません
  2. FOOは囲んでいるスコープ (「最上位」) で検索され、そこで見つかります (123)
于 2013-03-01T22:16:52.143 に答える