class << self
ist mehr als nur eine Art, Klassenmethoden zu deklarieren (obwohl es auf diese Weise verwendet werden kann). Wahrscheinlich haben Sie einige Nutzung wie gesehen:
class Foo
class << self
def a
print "I could also have been defined as def Foo.a."
end
end
end
Das funktioniert und ist äquivalent zu def Foo.a
, aber die Art und Weise funktioniert es ist ein wenig subtiler. Das Geheimnis ist, dass sich self
in diesem Kontext auf das Objekt Foo
bezieht, dessen Klasse eine eindeutige anonyme Unterklasse von Class
ist. Diese Unterklasse wird Foo
's Eigenklasse genannt. So def a
erstellt eine neue Methode namens a
in Foo
's Eigenklasse, zugänglich durch die normale Methode Aufrufsyntax: Foo.a
.
Jetzt ist an einem anderen Beispiel aussehen lassen:
str = "abc"
other_str = "def"
class << str
def frob
return self + "d"
end
end
print str.frob # => "abcd"
print other_str.frob # => raises an exception, 'frob' is not defined on other_str
Dieses Beispiel ist das gleiche wie die letzten, obwohl es schwierig sein kann, zunächst zu erzählen. frob
ist definiert, nicht auf die String
Klasse, sondern auf die Eigenklasse str
, eine einzigartige anonyme Unterklasse von String
. So str
hat eine frob
Methode, aber Instanzen von String
im Allgemeinen nicht. Wir könnten auch Methoden von String überschrieben haben (sehr nützlich in bestimmten schwierigen Testszenarien).
Jetzt sind wir bereit, Ihr ursprüngliches Beispiel zu verstehen. In der Foo
Initialisierungsmethode bezieht sich self
nicht auf die Klasse Foo
, sondern auf eine bestimmte Instanz von Foo
. Seine Eigenklasse ist eine Unterklasse von Foo
, aber sie ist nicht Foo
; es könnte nicht sein, sonst könnte der Trick, den wir im zweiten Beispiel sahen, nicht funktionieren. So um Ihr Beispiel fortzusetzen:
f1 = Foo.new(:weasels)
f2 = Foo.new(:monkeys)
f1.weasels = 4 # Fine
f2.monkeys = 5 # Also ok
print(f1.monkeys) # Doesn't work, f1 doesn't have a 'monkeys' method.
Hoffen, dass dies hilft.
So dann jede Instanz ist eine anonyme Unterklasse der Klasse erstellt? –
Die * Klasse * jeder Instanz ist eine anonyme Unterklasse der erstellten Klasse. Die Klasse von f1 ist eine anonyme Unterklasse von Foo. Die Klasse von Foo ist eine anonyme Unterklasse von Class. –
nette Antwort :) viele Leute verstehen das nicht so klar wie Sie. – horseyguy