我正在观看prag dave的第一个红宝石元编程截屏视频。在某些时候,他说当你向一个实例变量添加一个方法时,ruby会引入'ghost classes'。岛

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

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

有帮助吗?

解决方案

方法 speak 存储在元类(也称为本征类)中,你称之为“不可见代理类”。在Ruby中,实例变量没有地方存储方法。它们只能存储实例变量及其类。因此,当您向实例添加方法时,会创建元类并将其插入到其类链中。为了更好地理解内部,我建议这篇文章来自Klank Boom Klang。

为了获得元类,您可以执行以下操作:

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

其他提示

有些人称它为“Singleton Class”

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"]
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top