Question

Je regardais le premier screencast de métaprogrammation de ruby ??réalisé par prag dave. À un moment donné, il a dit que ruby ??introduisait des «classes fantômes» lorsque vous ajoutez une méthode à une variable d'instance. i.

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

Où est vraiment le magasin de méthode de parole? S'il s'agit d'une classe proxy invisible, comment pouvons-nous accéder à cette classe proxy?

Était-ce utile?

La solution

La méthode speak est stockée dans une métaclasse (également appelée classe propre), ce que vous appelez une "classe de proxy invisible". En Ruby, les variables d'instance n'ont pas de place pour stocker des méthodes. Ils ne peuvent stocker que des variables d'instance et leur classe. Ainsi, lorsque vous ajoutez une méthode à une instance, une métaclasse est créée et insérée dans sa chaîne de classes. Pour une meilleure compréhension des éléments internes, je recommande cet article de Klank Boom Klang.

Pour accéder à la méta-classe, vous pouvez procéder comme suit:

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

Autres conseils

Certains ppl l'appellent "Singleton Class"

singleton_class = class << animal; self; end

Et en réalité, cette classe singleton est l'hôte des méthodes de classe de toute classe. Vérifiez cet exemple, tout d'abord en définissant la classe Foo avec les méthodes de classe 'hi' et 'bye':

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

Définissons maintenant une méthode qui retourne la classe singleton pour nous:

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

Maintenant, essayez ceci:

Foo.singleton_methods #=> ["bye", "hi"]
Foo.singleton_class.instance_methods(false) #=> ["bye", "hi"]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top