2009-09-10 65 views
1

我正在觀看prag dave的第一個ruby元編程截屏視頻。在某個時候他說,當你向實例變量添加一個方法時,ruby會引入'ghost classes'。一世。如何在ruby中訪問ghost父類?

animal = "cat" 
def animal.speak 
    puts "hola" 
end 
animal.speak  # => hola 
animal.class  # => String 

dog = "dog" 

dog.speak   # Undefined method `speak' for "dog":String 
String.send :speak # NoMethodError: undefined method `speak' for String:Class 
animal.send :speak # hola 

真的說方法商店在哪裏? 如果它是一個隱形代理類,我們如何訪問該代理類?

回答

3

方法speak存儲在一個元類(也稱爲特徵類)中,您稱之爲「隱形代理類」。在Ruby中,實例變量沒有地方存儲方法。他們只能存儲實例變量和他們的類。因此,當您向實例添加方法時,會創建一個元類並將其插入其類鏈中。爲了更好地瞭解內部,我建議Klank Boom Klang的this article

爲了得到在元類,你可以做到以下幾點:

animal = "cat" 
def animal.speak 
    puts "hola" 
end 
animal.speak  # => hola 
animal.class  # => String 

metaclass = class << animal; self; end 

metaclass.inspect      # => #<Class:#<String:0x2c9c460>> 
metaclass.instance_methods.index 'speak' # => 102 
metaclass.class       # => Class 
+0

THX,那是一個很好的答案。 – Pedro 2009-09-10 15:45:38

1

一些脂肪酶稱之爲「單例類」

singleton_class = class << animal; self; end 

而實際上這個單例類是主機在這個例子中,首先通過用類方法'hi'和'bye'定義Foo類:

class Foo 
    def self.hi ; p "hi" ; end 
    def self.bye ; p "bye" ; end 
end 
Foo.singleton_methods #=> ["hi","bye"] 

現在讓我們來定義一個返回的單例類爲我們的方法:

class Object 
    def singleton_class 
    class << self 
     self 
    end 
    end 
end 

現在試試這個:

Foo.singleton_methods #=> ["bye", "hi"] 
Foo.singleton_class.instance_methods(false) #=> ["bye", "hi"]