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) # => []
-
当包括本征类时,
B.ancestors
和B.metaclass.ancestors
会是什么样子? 方法say_hello
存储在一个特征类中(我假设B.class
inheritance自)但是在哪里? -
由于有两个祖先链(
B.ancestors
和B.class.ancestors
或B.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
是多余的。