Die meisten in Ruby verwendeten Instanzmethoden sind globale Methoden. Das heißt, sie sind in allen Instanzen der Klasse verfügbar, für die sie definiert wurden. Im Gegensatz dazu ist eine Singleton-Methode nur für ein einziges Objekt implementiert.
Es besteht ein offensichtlicher Widerspruch. Ruby speichert Methoden in Klassen und alle Methoden müssen mit einer Klasse verbunden sein. Das Objekt, auf dem eine Singleton-Methode definiert ist, ist keine Klasse (es ist eine Instanz einer Klasse). Wenn nur Klassen Methoden speichern können, wie kann dann ein Objekt eine Singleton-Methode speichern? Wenn eine Singleton-Methode erstellt wird, erstellt Ruby automatisch eine anonyme Klasse, um diese Methode zu speichern. Diese anonymen Klassen werden als Metaklassen bezeichnet, auch bekannt als Singleton-Klassen oder Eigenklassen. Die Singleton-Methode ist mit der Metaklasse verbunden, die wiederum mit dem Objekt verbunden ist, für das die Singleton-Methode definiert wurde.
Wenn mehrere Singleton-Methoden innerhalb eines einzigen Objekts definiert sind, werden sie alle in derselben Metaklasse gespeichert.
class Zen
end
z1 = Zen.new
z2 = Zen.new
def z1.say_hello # Notice that the method name is prefixed with the object name
puts "Hello!"
end
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
Im obigen Beispiel wurde die Methode say_hello in der Instanz z1 der Klasse Zen definiert, nicht aber in der Instanz z2.
Das folgende Beispiel zeigt eine andere Art, eine Singleton-Methode zu definieren, mit dem gleichen Ergebnis.
class Zen
end
z1 = Zen.new
z2 = Zen.new
class << z1
def say_hello
puts "Hello!"
end
end
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
Im obigen Beispiel ändert class << z1 das aktuelle self so, dass es auf die Metaklasse des z1-Objekts verweist; dann wird die Methode say_hello innerhalb der Metaklasse definiert.
Die beiden obigen Beispiele dienen zur Veranschaulichung der Funktionsweise von Singleton-Methoden. Es gibt jedoch einen einfacheren Weg, eine Singleton-Methode zu definieren: mit einer eingebauten Methode namens define_singleton_method.
class Zen
end
z1 = Zen.new
z2 = Zen.new
z1.define_singleton_method(:say_hello) { puts "Hello!" }
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
Wir haben bereits gelernt, dass Klassen auch Objekte sind (Instanzen der eingebauten Klasse Class). Wir haben auch etwas über Klassenmethoden gelernt. Klassenmethoden sind nichts anderes als Singleton-Methoden, die mit einem Klassenobjekt verbunden sind.
Ein weiteres Beispiel:
class Zabuton
class << self
def stuff
puts "Stuffing zabuton…"
end
end
end
Alle Objekte können Metaklassen haben. Das bedeutet, dass auch Klassen Metaklassen haben können. Im obigen Beispiel modifiziert class << self self, so dass es auf die Metaklasse der Klasse Zabuton zeigt. Wenn eine Methode ohne expliziten Empfänger (die Klasse/das Objekt, auf dem die Methode definiert wird) definiert wird, wird sie implizit innerhalb des aktuellen Gültigkeitsbereichs definiert, d. h. dem aktuellen Wert von self. Die Methode stuff ist also innerhalb der Metaklasse der Klasse Zabuton definiert. Das obige Beispiel ist nur eine weitere Möglichkeit, eine Klassenmethode zu definieren.
Lesen Sie mehr unter diesen Beitrag über Ruby-Klassen .