4

さて、Ruby でメタプログラミングをしようとしていますが、少し混乱しています。私が読んだいくつかの記事 (この記事など) によると、Ruby クラスにクラス メソッドを動的に追加するには、クラスのシングルトン クラスを使用する必要があります。

class Klass
end

class << Klass
  self.define_method(:foo) { return "foo" }
end

これはなぜですか、それはこれとどのように違うのですか?

class Klass
  self.define_method(:foo) { return "foo" }
end

(この質問に誤った仮定が含まれている場合は申し訳ありません。私が言ったように、私は少し混乱しています。)

4

1 に答える 1

9

質問に直接答えるに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を持つクラスがある場合、 はインスタンス メソッドだけでなく、シングルトン メソッド継承します。つまり、のシングルトン クラスは のシングルトン クラスのスーパークラスとして扱われます。これは、他のオブジェクトのシングルトン クラスには当てはまりません。BABBA

于 2012-09-14T19:55:07.697 に答える