1

私はメタプログラミングRubyを読んでいて、次の言い換えられたコードについて何かを明らかにしたいと思っています。

class MyClazz
  def self.my_class_method(name)
    define_method(name) {
      # do stuff
    }
  end

  my_class_method :foo
  my_class_method :bar
end

# The code above generates instance methods:

# def foo
#   do stuff
# end

# def bar
#   do stuff
# end

Q1 私の最初の質問は、ファイルの最後にある2つのメソッド呼び出しに関するものです:my_class_method :foomy_class_method :bar。MyClazzオブジェクトがインスタンス化されると、両方が自動的に呼び出されると私は考えていますか?

Q2 Rubyがこれらのメソッド(def fooおよびdef bar)を生成すると、インスタンスメソッドであっても、MyClazzの固有クラスに配置されます。つまり、これは、Rubyが必要に応じてクラスメソッドとインスタンスメソッドの両方について固有クラスを参照することを意味しますか?

本の奥深くに移動する前に、それを明確にしたいだけです。

4

2 に答える 2

3

回答1:( 短い) rubyがMyClass(タイプのClass)インスタンスをインスタンス化するときに呼び出されます。

(long) Rubyインタープリターがクラス定義(class MyClazz)を見ると、このクラスのインスタンスをインスタンス化し、クラス定義内のすべてのコードを評価します。

あなたの場合MyClazzは、クラスのオブジェクトへの参照を保持する定数ですClass。そして、Rubyがそれを初期化すると、クラス定義内でコードを実行します-このインスタンスのシングルトンメソッドmy_class_methodを定義し、このインスタンスのコンテキストでClassメソッドを2回実行します。my_class_methodClass

回答2:( 短い) Module#define_methodプライベートメソッドは、インスタンスのメソッドテーブルにメソッドを追加しClassます(メソッドテーブルはクラスのインスタンスメソッドを保持します)。istanceオブジェクト/クラスオブジェクトの固有クラスには影響しません。

(long)オブジェクトでインスタンスメソッドを呼び出すと、Rubyは最初にこのメソッドをこのオブジェクトの固有クラスで検索し、次に固有クラスのスーパークラスで検索します(Classオブジェクトのクラスのオブジェクトになります)。ただし、オブジェクトの固有クラスは調べませんMyClazz

例:

obj = MyClazz.new
obj.foo # => ok

obj.foofooオブジェクトの固有クラスでメソッド定義を検索し、次に(クラスのインスタンス)objのインスタンスメソッドを検索し、次にオブジェクトのスーパークラス(この場合はクラス)などを検索します。MyClassClassMyClassObject

obj = MyClass.new
MyClass.my_class_method :baz
obj.baz # => ok

MyClass.my_class_methodmy_class_methodオブジェクトの固有クラスでメソッド定義を検索し(補足:クラスの固有クラスはメタクラスMyClassと呼ばれることもあります)、ここでそれを検索し、インスタンスメソッドをクラスに追加します。bazMyClass

于 2012-03-24T09:52:11.587 に答える
2

A1:はい、これらのメソッドはインスタンス化時に作成されます。

A2:Russ Olsenは、彼の著書EloquentRubyでこれを説明する素晴らしい仕事をしています。固有クラス(またはシングルトンクラス)は、「すべてのオブジェクトとその通常のクラスの間にあります」。そのため、Rubyがインスタンスメソッドで探しているメソッドを見つけられない場合、Rubyは継承ツリーを上に移動し始めます。次の目的地は固有クラスで、そこからクラス自体です。

Olsenは、すべてのClassメソッドが実際には新しいクラスとClassオブジェクトの間のシングルトンメソッドである方法についても興味深い議論をしています。

于 2012-03-24T04:59:45.970 に答える