11

Ruby オブジェクト モデルを理解しようとしています。インスタンスメソッドは、クラスのオブジェクトではなくクラスに保存されるため、冗長性がなくなることがわかりました。クラスが作成されるたびに、新しく作成されたクラスのメタクラスも作成されることを読みました。メタクラスはクラス メソッドを格納します。つまり、クラスのシングルトン メソッドはメタクラスに配置されます。例えば

class MyClass
  def hi
    'hi object'
  end

  def self.bye
    'bye singleton method'
  end
end

上記の MyClass に対して、メタクラス (#MyClass など) も作成されます。メソッド 'hi' はインスタンス レベルのメソッドになり、MyClass のすべてのオブジェクトで呼び出すことができます。メソッド 'bye' は MyClass のシングルトン メソッドであり、#MyClass に存在します。'hi' が MyClass のすべてのオブジェクトではなく MyClass に保存される理由 (私はそう思います) は、冗長性を避けるためです。ただし、MyClass という名前のクラスを複数持つことはできません。複数の MyClass を持つことはできないため、#MyClass ではなく MyClass に 'bye' を格納しないでください。なぜこれがそうなのかはまったくわかりませんが、その背後にある理由を理解しようとしています。

- - -アップデート - -

メタクラスには、シングルトン メソッドなどのクラス情報が格納されます。しかし、クラスはシングルトン オブジェクト (クラス Class のインスタンスであり、その型だけである) であるため、すべての情報をメタクラスではなくクラス自体に保存しないでください。

4

4 に答える 4

3

これはあなたの質問に対する完全な答えではありませんが、役に立つかもしれません。それについて考えるべき2つのことが役立つかもしれません:

  • メタクラスは、他のシナリオでメタプレフィックスがどのように使用されるかを考えると、ここで何が起こっているかを示す適切な名前ではありません。他のドキュメンテーションで使用されているeigenclassはおそらくより適切な名前であり、「オブジェクト自身のクラス」を意味します。
  • 固有クラスを持つのはクラスだけではなく、すべてのオブジェクトが持っています

固有クラスは、特定のオブジェクトに固有のメソッドを格納するために使用されます。たとえば、単一の String オブジェクトにメソッドを追加できます。

my_string = 'Example'
def my_string.example_method
  puts "Just an example"
end

このメソッドは、他の String オブジェクトに対してのみ呼び出すことができmy_string、他の String オブジェクトに対しては呼び出すことができません。の固有クラスに格納されていることがmy_stringわかります。

eigenclass = class << my_string; self; end # get hold of my_string's eigenclass
eigenclass.instance_methods(false) # => [:example_method]

クラスはオブジェクトであることを思い出すと、このコンテキストでは、特定のクラスに固有のメソッドをそのクラスの固有クラスに格納する必要があることは理にかなっています。


更新:実際には、固有クラスには固有クラスがあります。eigenclassObject にメソッドとして追加すると、これをより簡単に確認できます。

class Object 
  def eigenclass 
    class << self
      self
    end 
  end 
end

そして、次のことができます。

irb(main):049:0> my_string.eigenclass
=> #<Class:#<String:0x269ec98>>
irb(main):050:0> my_string.eigenclass.eigenclass
=> #<Class:#<Class:#<String:0x269ec98>>>
irb(main):051:0> my_string.eigenclass.eigenclass.eigenclass # etc!
=> #<Class:#<Class:#<Class:#<String:0x269ec98>>>>

これは一見すると無限後退を引き起こしますが、Ruby は必要なときにのみ固有クラスを作成するため、これは回避されます。「メタクラス」という名前は、「メタクラス」が実際には保持していないある種の情報を保持することを期待しているため、混乱の原因の一部だと思います。

于 2013-07-09T15:55:25.940 に答える
2

Rubyプログラミング言語による と、クラスメソッドは、クラスと同じ名前のクラスのインスタンスに対する実際のシングルトンメソッドです。

Class Foo
  def self.bar
    "Am a class method"
  end
end

ここで、メソッドは typeのインスタンスのシングルトン メソッドself.barとして表すことができます。FooClass Foo

#the following code is just to explain on what actually are class methods called
Foo.bar #=> "Am a class method" 
#the call is done on an instance of class Foo which got ref name Foo

Fooクラス/シングルトン/メタクラスメソッドをさらに追加することができます

class<<Foo
  def self.another_bar
    "Am another class method"
  end
end

Foo.another_bar #=>"Am another class method"

より正式には、シングルトン メソッドは匿名固有クラス/メタ クラスのインスタンス メソッドとして定義されます。

概念的には間違っていますが、理解を深めるために、このコンテキストではクラスをオブジェクトと見なすことができます。

この概念は、言語のすべてのレベルで真のオブジェクト指向性をもたらすために存在します。Objective-C は、同様の方法でクラス メソッドを実装します。

Obj-C では、メタクラスはクラスに関する情報を含むクラスとして救済されますmeta。また、継承の原則はメタクラスにも適用されます。スーパークラスはそのクラスのスーパークラスのメタクラスであり、ベースオブジェクトに到達するまで上昇します。そのメタクラスはメタクラスそのものです。詳細については、こちらを参照してください

于 2013-07-09T16:00:07.897 に答える