2009-05-08 7 views

答えて

4

、あなたは少し奇妙な場所にいますまたはそのような関数内でselfを見てみてください)、これらの関数はObjectクラス内のプライベートメソッドとして定義されています。

$ cat foo 
def foo 
    p self 
    p self.class 
    puts 'foo' 
end 

foo 
Object.foo 

$ ruby foo 
main 
Object 
foo 
foo:8: private method `foo' called for Object:Class (NoMethodError) 
$ 

あなたは明示的にこれらのメソッドpublicを宣言することでこの問題を回避こそこそすることができますが、私はこれが好きかわかりません!奇妙なことに、irbの中にトップレベルのメソッドを定義した場合は、それをpublic宣言することなく、クラスメソッドObject#fooで呼び出すことができます。

これは「Objectにハッキングされた(しかし、誰にも知らせない)」暗黙のメインネームスペースの一種です。 @fooは、トップレベルの関数の内部で定義されています。並べ替えあなたのトップレベルメソッドが@fooに設定されていて、それをスコープなしで呼び出すと、それは固有のようなmain名前空間で宣言されますが、Objectでクラスメソッドを呼び出すと@fooObjectのスペースに表示されます。

もう一つの例:

public 
def set_foo 
    @foo = 'foo' 
end 

def get_foo 
    @foo 
end 

def Object.get_foo_again 
    @foo 
end 

set_foo 
p get_foo 
p Object.get_foo_again 

Object.set_foo 
p Object.get_foo_again 

"foo" # @foo set in main 
nil # @foo nil in Object 
"foo" # @foo in Object 

逆も当てはまるできます。

1

モジュールにしていると思います。

3

これは「関数ではなくメソッドである」という前提が間違っています。すべてのRubyコードは、あるオブジェクトのコンテキスト内で発生します。 「グローバル」コンテキストは、mainというオブジェクトです(信じられない場合はruby -e "puts self"を試してください)。上のスコープで定義されたメソッドは、Objectのインスタンスメソッドになります。このメソッドは、メソッドが

+0

さて、モジュールレベルの関数内で@identは$ identを別の方法で表していますか? – cdleary

+1

いいえ、それはモジュールの@identインスタンス変数を設定します(Rubyではモジュールもオブジェクトであり、独自のivarsを持つことができます)。 "@ident = something"は、現時点の "self"の@identインスタンス変数を設定します。 – Chuck

+1

だから、グローバルは本当にグローバル(インタープリタにバインドされている)であり、モジュールの範囲に限定されません。 – cdleary

1

@と呼ばれる場所に応じてself(及びインスタンス変数が属するこうしてコンテキスト)で、どこでも利用できるようになりますが、可変インスタンス変数になることを意味します。明示的に宣言されたクラスの一部ではないように思えるので、Chuckが指摘したように、メインオブジェクト内で利用可能になります。それは、簡単に例で示されています:グローバル「メイン」スペース(あなたがirbを実行したときにプロンプ​​トが表示され、:トップレベルの機能(実際にはまだ法)で

$ irb 
irb(main):001:0> @var = 1 
=> 1 
irb(main):002:0> class New 
irb(main):003:1> def test 
irb(main):004:2>  puts @var 
irb(main):005:2> end 
irb(main):006:1> end 
=> nil 
irb(main):007:0> test = New.new 
=> #<New:0xb7ccbc14> 
irb(main):008:0> test.test 
nil 
=> nil 
irb(main):009:0> def test2 
irb(main):010:1> puts @var 
irb(main):011:1> end 
=> nil 
irb(main):012:0> test2 
1 
=> nil