0

Dave Thomas によるRuby オブジェクト モデルの講演で、Rubyには「クラス メソッド」はありません。メソッドの受け手が「クラスオブジェクト」か「インスタンスオブジェクト」かの違いだけです。

class Dave
  def InstaceMethod              ### will be stored in the current class (Dave)
    puts "Hi"
  end
  class << self                  ### Creates an eigenclass, if not created before
    def say_hello
      puts "Hello"
    end
  end
end

デフォルトでは、ancestorsメソッドはメタクラスを表示しません:

class Dave
  class << self
    def metaclass                ### A way to show the hidden eigenclass
      class << self; self; end
    end
  end
end

p Dave.ancestors
# => [Dave, Object, Kernel, BasicObject]
p Dave.metaclass.ancestors
# => [Class, Module, Object, Kernel, BasicObject]

ただし、実際のものは次のようになると思います。

# => [<eigenclass>, Class, Module, Object, Kernel, BasicObject]

p Dave.class.instance_method(false)
# => [:allocate, :new, :superclass]
p Dave.metaclass.instance_method(false)
# => [:say_hello, :metaclass]

今、継承。

class B < Dave
end

p B.say_hello
# => "Hello"
p B.ancestors
# => [B, Dave, Object, Kernel, BasicObject]
p B.class.instance_methods(false)
# => [:allocate, :new, :superclass]

以下は、 の新しい固有クラスを作成しますB

p B.metaclass.ancestors
# => [Class, Module, Object, Kernel, BasicObject]
p B.metaclass.instance_method(false)
# => []
  1. 固有クラスも含まれている場合、 と はどのように見えるB.ancestorsでしょうか? B.metaclass.ancestorsメソッドsay_helloは固有クラスに格納されていますが (B.class継承元であると想定しています)、それはどこにあるのでしょうか?

  2. 2 つの祖先チェーン (B.ancestorsおよびB.class.ancestorsまたはB.metaclass.ancestors) があるため、継承は実際にどのように行われるのでしょうか?

4

2 に答える 2

3

オブジェクト (およびオブジェクトであるクラス、クラスのインスタンス) には、そのクラスを指すクラス フィールドがあります。シングルトン クラス (固有クラス/メタクラス) を作成すると、匿名クラスが作成され、このポインターが匿名クラスを指すように変更され、そのクラス ポインターは元のクラスを指すようになります。このclassメソッドは匿名クラスを表示せず、元のクラスのみを表示します。ミックスインも同様です。クラスにはスーパークラス フィールドがあります。このメソッドincludeは匿名プロキシを作成し、スーパークラス ポインタは匿名プロキシ クラスを指すように変更され、そこからスーパークラスを指すようになります。メソッドancestorsは匿名クラスを表示しませんが、含まれているモジュールの名前を表示します。superclassメソッドは匿名プロキシ クラスを表示せず、元のスーパークラスのみを表示します。

これを読むことができます:なぜRubyのシンボルは変数のタイプと見なされないのですか?

この回答へのコメントには、Devalot ブログにあるシングルトン クラスに関する興味深い記事へのリンクがあります。

これらの継承チェーンを吸収するには、ある程度の時間が必要です。良い図は長い説明の価値があるので、これらすべてのチェーンについてのさまざまな図があるつるはしの第 24 章メタプログラミングをお勧めします。

デフォルトでは、祖先メソッドはメタクラスを表示しません:
そして 1. 固有クラスも含まれている場合、B.ancestors ... はどのように見えますか?

ancestorsスーパークラス チェーンに関するものです。固有クラスはスーパークラス チェーンに属していません。

p Dave.metaclass.ancestors
=> [Class, Module, Object, Kernel, BasicObject]
ただし、実際のものは次のようになると思います:
=> [ "eigenclass" , Class, Module, Object, Kernel, BasicObject]

正しい。

Dave クラスを単純化できます。

class Dave
    def self.say_hello    # another way to create an eigenclass, if not created before
      puts "Hello"
    end
    def self.metaclass    # A way to show the hidden eigenclass
        class << self
            self
        end
    end
end

Dave.say_hello           # => Hello
Dave.new.class.say_hello # => Hello
p Dave.metaclass.instance_methods(false) # => [:say_hello, :metaclass]
p Dave.singleton_methods                 # => [:say_hello, :metaclass]

def self.metaclassが導入された Ruby 1.9.2 以降、不要Object#singleton_classです。

于 2013-01-04T10:07:53.093 に答える
1

Eigenclassは卑劣な隠されたものです。あなたはクラスを開くことによってそれを首尾よく明らかにしました。しかし、それは通常のクラスの祖先には存在しません。また、非表示ancestorsになっているため、固有値クラス自体にメソッドを送信しても表示されません。継承ツリーは次のようになります。

B ---S-->  Dave   ---S---> Object  ---S---> BasicObject
|            |               |                  |
E            E               E                  E
|            |               |                  |
#B --S--> #Dave   ---S---> #Object ---S---> #BasicObject --S---> Class,,Object,BasicObject

Sスーパークラスを表し、固有クラスEを表します。

于 2013-01-04T09:39:06.313 に答える