質問に直接答えるにModule#define_method
は、インスタンス メソッドを作成します。「クラス メソッド」は、オブジェクトのシングルトン クラス (または固有クラス) のインスタンス メソッドClass
です。とても紛らわしいと思います。そもそもRubyに「シングルトンクラス」の概念が含まれている理由を説明しましょう。
まず、さまざまなオブジェクト指向言語の基本的な「フレームワーク」は非常に多様です。オブジェクト、クラス、メタクラスなどに関する Ruby の設計は決して唯一の可能なものではなく、言語は別の方法で設計された可能性があります。そうは言っても、Ruby がそのように機能するのには論理的な理由があります。できるだけ簡潔に説明しようと思います...
次のような単純なメソッド呼び出しを考えてみてください。
[1,2,3].first
first
ここでは、Array
オブジェクトをレシーバとして、というメソッドを呼び出しています。このメソッド呼び出しを処理するには、Ruby は一致するメソッド定義を検索して実行する必要があります。どこから探し始めますか?当然、 のインスタンス メソッドではArray
. そこに見つからない場合は、Array
のスーパークラス、次にスーパークラスのスーパークラス、またはそのスーパークラスにModule
混合されているなどを調べます。Array
「クラスベース」(プロトタイプベースではなく) のオブジェクト指向言語はすべて、多かれ少なかれこのように機能します。Java、C++、または Python でプログラミングしたことがある場合は、この動作に慣れているはずです。
さて、Ruby の作成者は、1 つのオブジェクトだけにメソッドを追加できるようにしたいと考えていました。プロトタイプベースの OO 言語では簡単ですが、クラスベースの言語ではどのように機能するのでしょうか? 彼は「シングルトンクラス」または「固有クラス」のアイデアを導入することでそれを可能にしました。
「シングルトン クラス」とは、簡単に言うと、インスタンスが1 つしかないクラスです。オブジェクトごとに異なるシングルトン クラスを追跡しようとするのではなく、Ruby はオブジェクトのシングルトン クラスに初めてアクセスしようとするまで待ってから、クラスを作成し、それをオブジェクトの継承チェーンに動的に挿入します。
先ほど言ったように、メソッドが呼び出されると、Ruby は最初にオブジェクトのクラスを調べて一致する定義を見つけ、次にスーパークラスなどを探します。シングルトン クラスはオブジェクトの継承チェーンの最初のリンクとして挿入されるため、最初の場所になります。どの Ruby がメソッド定義を探すか。
「シングルトン クラス」の概念を導入することで、別の問題も同時に解決されました。Java では (たとえば)、static
クラスで呼び出されるメソッドを定義できます。Ruby では、似たようなことをしたい人がよくいます。「シングルトン」クラスとメソッドを使用すると、まさにそれを行うことができます。必要なのは、Class オブジェクトでシングルトン メソッドを定義することだけです。
(Ruby ではクラスもオブジェクトであることを忘れないでください。上記で説明したように、"シングルトン" クラスとメソッドの概念が "一石二鳥" になるのはそのためです!)
追加情報:
冒頭で「インスタンスメソッド」について触れました。それが混乱を招くかどうか、または「インスタンスメソッド」が何であるかをすでに知っているかどうかはわかりません。Ruby クラスを定義すると、次のようになります。
class MyClass
def my_method
# do something
end
end
…のインスタンスメソッドとしてmy_method
追加されます。Ruby がオブジェクトのクラス、スーパークラスなどからメソッド定義を検索するとき、実際に参照するのはそれらのインスタンス メソッドです。したがって、オブジェクトの「メソッド」は、そのクラスのインスタンス メソッドに加えて、スーパークラスのインスタンス メソッド、スーパークラスのスーパークラスなどです。MyClass
Ruby でシングルトン クラスがメソッド ルックアップとどのように相互作用するかについては、上で述べなかった若干の矛盾があります。詳細に理解したい場合:
一般に、クラス オブジェクトのシングルトンクラスは、他のオブジェクトのシングルトン クラスとは少し異なる方法で扱われます。A
別のクラスから継承し、シングルトン メソッドB
を持つクラスがある場合、 はインスタンス メソッドだけでなく、シングルトン メソッドも継承します。つまり、のシングルトン クラスは のシングルトン クラスのスーパークラスとして扱われます。これは、他のオブジェクトのシングルトン クラスには当てはまりません。B
A
B
B
A