Kann mir jemand etwas über den Unterschied zwischen Klassenvariablen und Klasseninstanzvariablen sagen?Unterschied zwischen Klassenvariablen und Klasseninstanzvariablen?
Antwort
Eine Klassenvariable (@@
) wird von der Klasse und allen ihren Nachkommen gemeinsam verwendet. Eine Klasseninstanzvariable (@
) wird von den Nachkommen der Klasse nicht gemeinsam verwendet.
Klassenvariable (@@
)
Beginnen wir mit einer Klasse eine Klasse Foo haben variable @@i
und Zugriffsmethoden für das Lesen und Schreiben von @@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 für @@i
haben:
p Foo.i # => 1
p Bar.i # => 1
und wechselnden @@i
in einer in beide verändert:
Bar.i = 2
p Foo.i # => 2
p Bar.i # => 2
Klasseninstanzvariable (@
)
Wir machen eine einfache Klasse mit einer Klasseninstanz va riablen @i
und Zugriffsmethoden für das Lesen und Schreiben von @i
:
class Foo
@i = 1
def self.i
@i
end
def self.i=(value)
@i = value
end
end
und einer abgeleiteten Klasse:
class Bar < Foo
end
Wir sehen, dass, obwohl Bar die Accessoren für @i
erbt, ist es nicht @i
selbst nicht erben:
p Foo.i # => 1
p Bar.i # => nil
Wir können Bar @i
ohne Auswirkungen auf Foosetzen:
Bar.i = 2
p Foo.i # => 1
p Bar.i # => 2
Zuerst müssen Sie verstehen, dass Klassen-Instanzen auch sind - Instanzen der Class
Klasse.
Sobald Sie das verstanden haben, können Sie verstehen, dass einer Klasse Instanzvariablen zugeordnet werden können, so wie es ein reguläres (read: non-class) Objekt kann.
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!"
Hinweis, dass ein Instanz-Variable auf Hello
zu völlig unabhängig ist und getrennt von einer Instanzvariablen auf einer Instanz von Hello
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!"
A Klassenvariable auf der anderen Seite ist eine Art der Kombination der obigen zwei, wie es auf Hello
selbst und seinen Instanzen, sowie auf Unterklassen von Hello
und ihren 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
zu vermeiden, weil der seltsame Verhalten oben, und die Verwendung von class instance variables
stattdessen empfehlen.
Warum Instanzvariablen mit Klassenmethoden zurückgeben? Findest du oft diese Situation? – sekmo
@sekmo Die Accessoren in diesen Beispielen geben entweder _class instance variables_ zurück, die zur Klasse gehören, oder _class variables_, die zur Klassenhierarchie gehören. Sie geben keine plain _instance-Variablen_ zurück, die zu Instanzen der Klasse gehören. Die Begriffe "Instanzvariable", "Klasseninstanzvariable" und "Klassenvariable" sind ziemlich verwirrend, nicht wahr? –