Antworten:
Eine Klassenvariable ( @@
) wird von der Klasse und allen ihren Nachkommen gemeinsam genutzt. Eine Klasseninstanzvariable ( @
) wird von den Nachkommen der Klasse nicht gemeinsam genutzt.
Klassenvariable ( @@
)
Lassen Sie uns eine Klasse Foo mit einer Klassenvariablen @@i
und Accessoren zum Lesen und Schreiben haben @@i
:
class Foo
@@i = 1
def self.i
@@i
end
def self.i=(value)
@@i = value
end
end
Und eine abgeleitete Klasse:
class Bar < Foo
end
Wir sehen, dass Foo und Bar den gleichen Wert haben für @@i
:
p Foo.i # => 1
p Bar.i # => 1
Und das Ändern @@i
in einem ändert es in beiden:
Bar.i = 2
p Foo.i # => 2
p Bar.i # => 2
Klasseninstanzvariable ( @
)
@i
Erstellen wir eine einfache Klasse mit einer Klasseninstanzvariablen und Accessoren zum Lesen und Schreiben @i
:
class Foo
@i = 1
def self.i
@i
end
def self.i=(value)
@i = value
end
end
Und eine abgeleitete Klasse:
class Bar < Foo
end
Wir sehen, dass Bar zwar die Accessoren für erbt @i
, sich aber nicht @i
selbst erbt :
p Foo.i # => 1
p Bar.i # => nil
Wir können Bar's setzen, @i
ohne Foo's zu beeinflussen @i
:
Bar.i = 2
p Foo.i # => 1
p Bar.i # => 2
Zuerst müssen Sie verstehen, dass Klassen auch Instanzen sind - Instanzen der Class
Klasse.
Sobald Sie das verstanden haben, können Sie verstehen, dass einer Klasse Instanzvariablen zugeordnet werden können, genau wie es einem regulären Objekt (sprich: Nicht-Klasse) möglich ist.
Hello = Class.new
# setting an instance variable on the Hello class
Hello.instance_variable_set(:@var, "good morning!")
# getting an instance variable on the Hello class
Hello.instance_variable_get(:@var) #=> "good morning!"
Beachten Sie, dass eine Instanzvariable ein Hello
völlig unabhängig von einer Instanzvariablen in einer Instanz von ist und sich von dieser unterscheidetHello
hello = Hello.new
# setting an instance variable on an instance of Hello
hello.instance_variable_set(:@var, :"bad evening!")
# getting an instance variable on an instance of Hello
hello.instance_variable_get(:@var) #=> "bad evening!")
# see that it's distinct from @var on Hello
Hello.instance_variable_get(:@var) #=> "good morning!"
Eine Klassenvariable ist andererseits eine Art Kombination der beiden oben genannten, da sie auf sich Hello
selbst und ihre Instanzen sowie auf Unterklassen Hello
und deren Instanzen zugänglich ist :
HelloChild = Class.new(Hello)
Hello.class_variable_set(:@@class_var, "strange day!")
hello = Hello.new
hello_child = HelloChild.new
Hello.class_variable_get(:@@class_var) #=> "strange day!"
HelloChild.class_variable_get(:@@class_var) #=> "strange day!"
hello.singleton_class.class_variable_get(:@@class_var) #=> "strange day!"
hello_child.singleton_class.class_variable_get(:@@class_Var) #=> "strange day!"
Viele Leute sagen, class variables
wegen des seltsamen Verhaltens oben zu vermeiden , und empfehlen die Verwendung von class instance variables
stattdessen.
Außerdem möchte ich hinzufügen, dass Sie @@
von jeder Instanz der Klasse aus Zugriff auf die Klassenvariable ( ) erhalten können
class Foo
def set_name
@@name = 'Nik'
end
def get_name
@@name
end
end
a = Foo.new
a.set_name
p a.get_name # => Nik
b = Foo.new
p b.get_name # => Nik
Sie können jedoch nicht dasselbe für die Klasseninstanzvariable ( @
) tun
class Foo
def set_name
@name = 'Nik'
end
def get_name
@name
end
end
a = Foo.new
a.set_name
p a.get_name # => Nik
b = Foo.new
p b.get_name # => nil
Foo.i
, aber wie können Sie dasselbe für jede Instanz dieser Klasse wie tun Foo.new.i
?
#class
. Ich persönlich denke, dass #class
Verwendungen, wenn sie auf etwas aufgerufen werden, aber self
Code-Gerüche sind. Sie können sogar noch einen Schritt weiter gehen und die Instanz Accessoren implementieren i
und i=
dass die Delegierten ihre #class
Äquivalente, wobei in diesem Fall die Sie tun können Foo.new.i
. Ich empfehle dies nicht, da dadurch eine verwirrende Oberfläche entsteht, die darauf hindeutet, dass Sie ein Objektmitglied ändern.