代码之家  ›  专栏  ›  技术社区  ›  Pedro

如何访问Ruby中的Ghost父类?

  •  2
  • Pedro  · 技术社区  · 17 年前

    我在看PragDave的第一个Ruby元编程屏幕。在某种程度上,他说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
    

    口语方法商店在哪里? 如果它是一个不可见的代理类,我们如何访问该代理类?

    2 回复  |  直到 17 年前
        1
  •  4
  •   Pesto    17 年前

    方法 speak 存储在一个元类(也称为本征类)中,您称之为“不可见代理类”。在Ruby中,实例变量没有存储方法的位置。它们只能存储实例变量及其类。因此,当向实例添加方法时,将创建一个元类并将其插入到其类链中。为了更好地理解内部结构,我建议 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
    
        2
  •  1
  •   khelll    17 年前

    一些PPL称之为“单身阶级”

    singleton_class = class << animal; self; end
    

    实际上,这个singleton类是任何类的类方法的宿主,检查这个例子,首先用类方法“hi”和“bye”定义类foo:

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

    现在让我们定义一个返回singleton类的方法:

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

    现在试试这个:

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