135

Przeczytałem "When do Ruby instance variables get set?", ale mam dwa umysły, gdy używam zmiennych instancji klasy.Zmienna instancji klasy Ruby vs. zmienna klasy

Zmienne klasy są wspólne dla wszystkich obiektów klasy, zmienne instancji należą do jednego obiektu. Nie mamy zbyt wiele miejsca, aby używać zmiennych instancji klasy, jeśli mamy zmienne klasy.

Czy ktoś mógłby wyjaśnić różnicę między tymi dwoma i kiedy ich użyć?

Oto przykładowy kod:

class S 
    @@k = 23 
    @s = 15 
    def self.s 
    @s 
    end 
    def self.k 
    @@k 
    end 

end 
p S.s #15 
p S.k #23 

Rozumiem teraz, Zmienne klasy instancji nie są przekazywane wzdłuż łańcucha dziedziczenia!

Odpowiedz

195

instancji zmiennej na klasy:

class Parent 
    @things = [] 
    def self.things 
    @things 
    end 
    def things 
    self.class.things 
    end 
end 

class Child < Parent 
    @things = [] 
end 

Parent.things << :car 
Child.things << :doll 
mom = Parent.new 
dad = Parent.new 

p Parent.things #=> [:car] 
p Child.things #=> [:doll] 
p mom.things #=> [:car] 
p dad.things #=> [:car] 

Klasa zmienna:

class Parent 
    @@things = [] 
    def self.things 
    @@things 
    end 
    def things 
    @@things 
    end 
end 

class Child < Parent 
end 

Parent.things << :car 
Child.things << :doll 

p Parent.things #=> [:car,:doll] 
p Child.things #=> [:car,:doll] 

mom = Parent.new 
dad = Parent.new 
son1 = Child.new 
son2 = Child.new 
daughter = Child.new 

[ mom, dad, son1, son2, daughter ].each{ |person| p person.things } 
#=> [:car, :doll] 
#=> [:car, :doll] 
#=> [:car, :doll] 
#=> [:car, :doll] 
#=> [:car, :doll] 

z instancją zmiennej w klasie (nie na przykład tej klasy) można przechowywać coś wspólnego temu klasa bez podklas automatycznie je również pobiera (i na odwrót). Dzięki zmiennym klasy masz wygodę polegającą na tym, że nie musisz pisać self.class z obiektu instancji i (jeśli jest to pożądane), automatycznie udostępnisz w hierarchii klas.


Scalanie je razem w jeden przykład, który obejmuje również zmienne instancji w przypadkach:

class Parent 
    @@family_things = [] # Shared between class and subclasses 
    @shared_things = [] # Specific to this class 

    def self.family_things 
    @@family_things 
    end 
    def self.shared_things 
    @shared_things 
    end 

    attr_accessor :my_things 
    def initialize 
    @my_things = []  # Just for me 
    end 
    def family_things 
    self.class.family_things 
    end 
    def shared_things 
    self.class.shared_things 
    end 
end 

class Child < Parent 
    @shared_things = [] 
end 

A potem w akcji:

mama = Parent.new 
papa = Parent.new 
joey = Child.new 
suzy = Child.new 

Parent.family_things << :house 
papa.family_things << :vacuum 
mama.shared_things << :car 
papa.shared_things << :blender 
papa.my_things  << :quadcopter 
joey.my_things  << :bike 
suzy.my_things  << :doll 
joey.shared_things << :puzzle 
suzy.shared_things << :blocks 

p Parent.family_things #=> [:house, :vacuum] 
p Child.family_things #=> [:house, :vacuum] 
p papa.family_things #=> [:house, :vacuum] 
p mama.family_things #=> [:house, :vacuum] 
p joey.family_things #=> [:house, :vacuum] 
p suzy.family_things #=> [:house, :vacuum] 

p Parent.shared_things #=> [:car, :blender] 
p papa.shared_things #=> [:car, :blender] 
p mama.shared_things #=> [:car, :blender] 
p Child.shared_things #=> [:puzzle, :blocks] 
p joey.shared_things #=> [:puzzle, :blocks] 
p suzy.shared_things #=> [:puzzle, :blocks] 

p papa.my_things  #=> [:quadcopter] 
p mama.my_things  #=> [] 
p joey.my_things  #=> [:bike] 
p suzy.my_things  #=> [:doll] 
30

Wierzę głównym (tylko?) Różni się od spadków:

class T < S 
end 

p T.k 
=> 23 

S.k = 24 
p T.k 
=> 24 

p T.s 
=> nil 

zmienne klasowe są wspólne dla wszystkich instancji klasy „” (tzn podklas), natomiast klasa zmienne instancji są specyficzne tylko dla tej klasy. Ale jeśli nigdy nie zamierzasz rozszerzyć swojej klasy, różnica jest czysto akademicka.

18

#class zmiennej instancji są dostępne tylko dla klasy metody, a nie metody instancji, podczas gdy zmienna klasy jest dostępna zarówno dla metod instancji, jak i metod klasy. Również zmienne instancji klasy są tracone w łańcuchu dziedziczenia, podczas gdy zmienne klas nie.

class Vars 

    @class_ins_var = "class instance variable value" #class instance variable 
    @@class_var = "class variable value" #class variable 

    def self.class_method 
    puts @class_ins_var 
    puts @@class_var 
    end 

    def instance_method 
    puts @class_ins_var 
    puts @@class_var 
    end 
end 

Vars.class_method 

puts "see the difference" 

obj = Vars.new 

obj.instance_method 

class VarsChild < Vars 


end 

VarsChild.class_method 
12

Jak powiedzieli inni, zmienne klasowe są wspólne dla danej klasy i jej podklas. Zmienne instancji klasy należą do dokładnie jednej klasy; jego podklasy są oddzielne.

Dlaczego to zachowanie istnieje? Cóż, wszystko w Ruby jest klasą obiektową. Oznacza to, że każda klasa ma przedmiot odpowiadający klasie Class (lub raczej podklasę Class). (Kiedy mówisz: class Foo, naprawdę deklarujesz stałą wartość Foo i przypisujesz do niej obiekt klasy.) Każdy obiekt Ruby może mieć zmienne instancji, więc obiekty klasy mogą mieć również zmienne instancji.

Problem polega na tym, że zmienne instancji na obiektach klas tak naprawdę nie zachowują się tak, jak zwykle zachowują się zmienne klasy. Zazwyczaj chcesz, aby zmienna klasy zdefiniowana w superklasie była współużytkowana z jej podklasami, ale nie jest to działanie zmiennych instancji - podklasa ma własny obiekt klasy, a obiekt klasy ma własne instancje. Dlatego wprowadzili oddzielne zmienne klasy z zachowaniem, którego najprawdopodobniej chcesz.

Innymi słowy, zmienne instancji klasy są swego rodzaju przypadkiem projektu Ruby. Prawdopodobnie nie powinieneś ich używać, chyba że wiesz dokładnie, że są tym, czego szukasz.

+0

A więc zmienna klasy jest jak zmienna statyczna w Javie? –

Powiązane problemy