Meine folgenden Notizen stammen aus Metaprogramming Ruby (by Paolo Perrotta), die ich zufällig gerade gelesen habe, als ich auf Ihre Frage stieß. Ich hoffe, dass diese Auszüge (Seitenzahlen in Klammern) und meine Erklärung hilfreich für Sie sind.
Beachten Sie, dass Klassenvariablen unterscheiden sich von Klasse Instanzvariablen.
A-Klasse Instanzvariable gehört zu einem Objekt der Klasse Class
und ist zugänglich nur durch die Klasse selbst - nicht durch eine Instanz oder durch eine Unterklasse. (106)
Die Klassenvariable, auf der anderen Seite gehört zur Klasse Hierarchien. Das bedeutet, dass es zu jeder Klasse sowie allen Nachkommen dieser Klasse gehört. Hier
ist ein Beispiel des Autors:
@@v = 1
class MyClass
@@v = 2
end
@@v # => 2
Sie dieses Ergebnis erhalten, weil Klassenvariablen wirklich nicht zu Klassen gehören - sie gehören zu der Klasse Hierarchien. Da @@ v in im Kontext von main
definiert ist, gehört es zu main's
Klasse Object
... und zu alle Nachkommen von Object
. MyClass
erbt von Object
, also es teilt sich die gleiche Klassenvariable. (107)
Aber auch, da Ihre spezielle Frage hat mit Klassen nicht zu tun, nur, sondern auch mit den Modulen:
Wenn Sie ein Modul in einer Klasse gehören, Ruby eine anonyme Klasse erstellen Dadurch wird das Modul umbrochen und die anonyme Klasse in die -Kette oberhalb der einschließenden Klasse eingefügt.(26)
So, wie Sie bei B.ancestors
anschauen, werden Sie sehen:
=> [B, A, Object, Kernel, BasicObject]
Auch für C.ancestors
, werden Sie sehen:
=> [C, A, Object, Kernel, BasicObject]
Wenn wir bedenken, dass Klassenvariablen gehören zu Klassenhierarchien, dann die Klassenvariable @@foo
, sobald sie in Module A
definiert ist (und so die anonyme Klasse knapp über B
tha t ist erstellt, sobald B
enthält A
), gehört zu B
(und auch zu C
, da es A
enthält).
Um es einfach auszudrücken:
- Wenn
@@foo
nur in B
und (aber nicht in A
) in C
definiert wurde, dann B
hatte eine Klassenvariable @@foo
, die anders als die Klassenvariable @@foo
in C
war. Dies liegt daran, dass die Klassenvariablen nur für diese Klasse und für alle Nachkommen zugänglich sind. Aber B
und C
sind durch ihre Vorfahren A
und nicht durch ihre Nachkommen verwandt.
- Sobald
@@foo
in A
definiert wurde, wurde diese Klassenvariable von allen Nachkommen von A
geerbt - also B
und C
. Von nun an verweist die Referenz auf @@foo
in Klasse B
tatsächlich auf die Klassenvariable, die zu A
gehört. Das Original @@foo
, das in B
definiert wurde, wurde überschrieben ersetzt (übernommen von seinem Vorfahren). Dasselbe ist mit der @@foo
in passiert. B
und C
können sowohl in dieselbe Klassenvariable @@foo
schreiben als auch von ihr lesen, da sie zu ihrem gemeinsamen Vorfahren A
gehört.
An dieser Stelle jemand von A
, B
oder C
können alle @@foo
ändern. Zum Beispiel:
class B
p @@foo # => 3
@@foo = 1
end
module A
p @@foo # => 1
end
@ArupRakshit Das ist nicht die Antwort. Eigentlich kam meine Frage aus dieser Antwort. Ihre Antwort ist der Ausgangspunkt dieser Frage. – sawa
Ich habe das .. Lass mich nachdenken .. :-) Gute Frage. –