2013-01-04 40 views
0

根据戴夫托马斯在his talk about the Ruby Object Model,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] 

下会创建一个新的eigenclass为B

p B.metaclass.ancestors 
# => [Class, Module, Object, Kernel, BasicObject] 
p B.metaclass.instance_method(false) 
# => [] 
  1. 将如何B.ancestorsB.metaclass.ancestors的样子时,也被包括在eigenclasses?方法say_hello存储在本征类(我假设B.class继承自),但它在哪里?

  2. 由于有两个祖先链(B.ancestorsB.class.ancestorsB.metaclass.ancestors),继承是如何发生的?

回答

1

本征类是一个偷偷摸摸的隐藏的。你已经成功地透过开课了。但它并不存在于普通阶级的祖先中。并且因为它是隐藏,您不能通过将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 eigenclass。

2

一个对象(也是一个对象,Class实例的类)有一个指向它的类的类字段。创建一个单例类(eigenclass/metaclass)将创建一个匿名类并将此指针更改为指向匿名类,该类的指针将指向原始类。 class方法不显示匿名类,只显示原始类。 mixin也一样。一个类有一个超类字段。方法include创建一个匿名代理,将超类指针更改为指向匿名代理类,并从那里指向超类。方法ancestors不显示匿名类,但是包含模块的名称。 superclass方法不显示匿名代理类,只显示原始超类。

您可以参阅:Why are symbols in Ruby not thought of as a type of variable?

在这个答案的注释,有对单例类的有趣的文章,可以在Devalot博客上找到的链接。

需要一些时间来吸收这些继承链。作为一个好的图片值得一个长时间的解释,我建议在镐http://pragprog.com/book/ruby3/programming-ruby-1-9第24章元编程,其中有关于所有这些链的各种图片。

默认情况下,祖先方法不显示元类:
和1将如何B.ancestors ......看起来像时也被包括在eigenclasses?

ancestors涉及超类链。本征类不属于超类链。

p Dave.metaclass.ancestors
=> [类,模块,对象,内核BasicObject]
然而,我假定真正的一个会是这样的:
=> [“eigenclass”,Class,Module,Object,Kernel,BasicObject]

正确。

您可以简化您的戴夫类:

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是因为红宝石1.9.2,里面有介绍Object#singleton_class多余的。