2010-09-27 8 views

Antwort

132

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 
+0

Warum Instanzvariablen mit Klassenmethoden zurückgeben? Findest du oft diese Situation? – sekmo

+0

@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? –

59

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.

+0

+1 für die Gliederung, dass Klassen Instanzen von 'Class' sind – mikezter

+1

+1 Super Erklärung! Dies ist etwas, was jeder Programmierer, der neu in Ruby ist, verdauen sollte. – TomZ