Frage

Ich war das erste Rubin metaprogramming Screencasts von prag dave beobachten. Irgendwann sagte er, dass Rubin "Geister Klassen einführen, wenn Sie eine Methode zu einer Instanzvariablen hinzufügen. 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

Wo ist wirklich die sprechen Methode speichern? Wenn es eine unsichtbare Proxy-Klasse ist: Wie können wir auf diese Proxy-Klasse zugreifen?

War es hilfreich?

Lösung

Das Verfahren speak in einem metaclass (auch als Eigenklasse genannt) gespeichert, was Sie eine „unsichtbare Proxy-Klasse“ nennen. In Ruby hat Instanzvariablen keinen Platz Methoden zu speichern. Sie können nur Instanzvariablen und ihre Klasse speichern. Also, wenn Sie eine Methode zu einer Instanz hinzufügen, wird ein Metaklasse erstellt und in seine Klasse Kette eingefügt. Zum besseren Verständnis der Einbauten, empfehle ich diesem Artikel aus Klank Boom Klang.

Um bei der Meta-Klasse zu erhalten, können Sie wie folgt vor:

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

Andere Tipps

Einige ppl nennen es "Singleton Klasse"

singleton_class = class << animal; self; end

Und tatsächlich diese Singletonklasse ist der Host für Klassenmethoden in jeder Klasse, lesen Sie in diesem Beispiel zunächst durch die Definition der Klasse Foo mit Klassenmethoden ‚hallo‘ und ‚bye‘:

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

Nun wollen wir eine Methode definieren, die für uns die Singleton-Klasse gibt zurück:

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

Jetzt versuchen Sie dies:

Foo.singleton_methods #=> ["bye", "hi"]
Foo.singleton_class.instance_methods(false) #=> ["bye", "hi"]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top