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 @@iund 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 @@iin einem ändert es in beiden:
Bar.i = 2
p Foo.i # => 2
p Bar.i # => 2
Klasseninstanzvariable ( @)
@iErstellen 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 @iselbst erbt :
p Foo.i # => 1
p Bar.i # => nil
Wir können Bar's setzen, @iohne 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 ClassKlasse.
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 Hellovö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 Helloselbst und ihre Instanzen sowie auf Unterklassen Hellound 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 variableswegen des seltsamen Verhaltens oben zu vermeiden , und empfehlen die Verwendung von class instance variablesstattdessen.
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 #classVerwendungen, wenn sie auf etwas aufgerufen werden, aber selfCode-Gerüche sind. Sie können sogar noch einen Schritt weiter gehen und die Instanz Accessoren implementieren iund 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.