2013-01-04 70 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多餘的。