inheritance如何在Ruby中工作?

根据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 < [Dave, Object, Kernel, BasicObject] p Dave.metaclass.ancestors # => [Class, Module, Object, Kernel, BasicObject] 

但是,我认为真实的将是这样的:

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

现在是inheritance。

 class B  "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.ancestorsB.metaclass.ancestors会是什么样子? 方法say_hello存储在一个特征类中(我假设B.classinheritance自)但是在哪里?

  2. 由于有两个祖先链( B.ancestorsB.class.ancestorsB.metaclass.ancestors ),实际上如何进行inheritance?

Eigenclass是一个偷偷摸摸的隐藏的。 你已经通过开课成功地揭示了它。 但它并不存在于普通阶级的祖先中。 而且由于它是隐藏的 ,你不能通过将ancestors方法发送给本征类本身来看到它。 inheritance树如下所示:

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

S代表超类,而E代表本征类。

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

你可以读到: 为什么Ruby中的符号不​​被认为是一种变量?

在对这个答案的评论中,有一个关于单例类的有趣文章的链接,可以在Devalot博客上找到。

人们需要一些时间来吸收这些inheritance链。 由于好的图片值得长篇解释,我建议在Pickaxe http://pragprog.com/book/ruby3/programming-ruby-1-9中进行第24章元编程,其中包含有关所有这些链的各种图片。

默认情况下,祖先方法不显示元类:
和B.ancestors如何…当特征类也被包括在内时?

ancestors关注的是超级链。 特征类不属于超类链。

p Dave.metaclass.ancestors
=> [类,模块,对象,内核,BasicObject]
但是,我认为真实的将是这样的:
=> [ “eigenclass” ,类,模块,对象,内核,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] 

自从Ruby 1.9.2引入了Object#singleton_class以来, def self.metaclass是多余的。