7

トップレベルでは、メソッド定義はプライベートメソッド on になるはずでObjectあり、テストはこれを裏付けているようです:

def hello; "hello world"; end

Object.private_instance_methods.include?(:hello) #=> true
Object.new.send(:hello) #=> "hello world"

ただし、以下はトップレベルでも機能します (self.metaは の固有クラスですmain)。

self.meta.private_instance_methods(false).include?(:hello) #=> true

このhelloメソッドは、 main の固有クラスと on で同時に定義されているようObjectです。どうしたの?falseパラメータ toprivate_instance_methodsは、メソッド リストからスーパー クラス メソッドを除外することに注意してください。

4

1 に答える 1

8

まず第一に、この振る舞いとその根底にある推論は常に存在していました。1.9 にとって新しいことではありません。これが発生する技術的な理由は、mainが特別であり、他のオブジェクトとは異なる方法で処理されるためです。派手な説明はありません。そのように設計されているため、そのように動作します。

わかりましたが、なぜですか?main魔法使いになる根拠は?Ruby の設計者 Yukihiro Matsumoto は、この振る舞いが言語をより良くすると考えているからです:

では、トップレベルのメソッドが Object クラス自体のインスタンス メソッドとして取り込まれるのではなく、このオブジェクトのシングルトン メソッドにならないのはなぜですか (したがって、他のすべてのクラスに、つまり、通常意図されているよりも多くの名前空間汚染が発生します)。これにより、トップレベルのメソッドが他のトップレベルのメソッドを呼び出すことができます。また、最上位オブジェクトが Main などの定数によって参照される場合、これらのメソッドは Main.method(...) を使用してどこからでも呼び出すことができます。

どこにでも「Main.print」と入力しますか?

さらに議論の中で、彼は「仮定が自然である」と感じているため、このように振る舞うと説明しています。

編集:

あなたのコメントに応えて、あなたの質問は、メインの固有クラスhelloがプライベート インスタンス メソッドとして報告されているように見える理由を対象としています。問題は、トップレベルの関数が実際に に追加されるmainのではなく、 に直接追加されることObjectです。固有クラスをinstance_methods扱う場合、関数のファミリは常に、固有クラスがまだ元のクラスであるかのように動作します。つまり、クラスで定義されたメソッドは、固有クラスで直接定義されているものとして扱われます。例えば:

class Object
  private
  def foo
    "foo"
  end
end

self.send :foo  # => "foo"
Object.private_instance_methods(false).include? :foo  # => true
self.meta.private_instance_methods(false).include? :foo  # => true

class Bar
  private
  def bar
    "bar"
  end
end

bar = Bar.new
bar.send :bar  # => "bar"
Bar.private_instance_methods(false).include? :bar  # => true
bar.meta.private_instance_methods(false).include? :bar  # => true

ただし、メソッドを の固有クラスに直接追加することはできmainます。元の例をこれと比較してください:

def self.hello; "hello world"; end

Object.instance_methods.include? :hello  # => false
self.meta.instance_methods.include? :hello  # => true

わかりましたが、特定の関数が元のクラスではなく、固有クラスで定義されていることを本当に知りたい場合はどうすればよいでしょうか?

def foo; "foo"; end  #Remember, this defines it in Object, not on main
def self.bar; "bar"; end  #This is defined on main, not Object

foo  # => "foo"
bar  # => "bar"

self.singleton_methods.include? :foo  # => false
self.singleton_methods.include? :bar  # => true
于 2009-11-19T19:59:13.940 に答える