2009-09-10 80 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"]