135

Я читал «When do Ruby instance variables get set?», но я имею в виду, когда использовать переменные экземпляра класса.Переменная экземпляра класса Ruby в сравнении с переменной класса

Переменные класса разделяются всеми объектами класса, переменные экземпляра относятся к одному объекту. Осталось немного места, чтобы использовать переменные экземпляра класса, если у нас есть переменные класса.

Может ли кто-нибудь объяснить разницу между этими двумя и когда их использовать?

Вот пример кода:

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 

теперь я понимаю, класс Переменные экземпляра не передаются по цепочке наследования!

ответ

195

переменная экземпляра на классе:

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] 

переменной Класс:

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] 

С переменной экземпляра на классе (не на экземпляр этого класса), вы можете хранить что-то общее в том, что класс, не имея подклассов, автоматически также получает их (и наоборот). С переменными класса вам удобнее не писать self.class из объекта экземпляра, и (при желании) вы также получаете автоматическое разделение по иерархии классов.


Объединение их вместе в одном примере, который охватывает также переменные экземпляра в случаях:

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 

А потом в действии:

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

Я считаю, что основной (только?) Отличается наследование:

class T < S 
end 

p T.k 
=> 23 

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

p T.s 
=> nil 

Переменные класса являются общими для всех экземпляров класса «» (то есть подклассы), тогда как переменные экземпляра класса являются специфическими только для этого сорта. Но если вы никогда не намереваетесь продлить свой класс, разница будет чисто академической.

18

#class переменной экземпляра доступны только для класса метод, а не метод экземпляра, тогда как переменная класса avilable как для методов экземпляра, так и для методов класса. Кроме того, переменные экземпляра класса теряются в цепочке наследования, тогда как переменные класса - нет.

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

Как уже отмечалось, переменные класса разделяются между данным классом и его подклассами. Переменные экземпляра класса относятся к одному классу; его подклассы являются отдельными.

Почему такое поведение существует? Ну, все в Ruby - это объект-четные классы. Это означает, что каждый класс имеет объект класса Class (или, скорее, подкласс Class), соответствующий ему. (Когда вы говорите class Foo, вы действительно объявляете константу Foo и присваиваете ему объект класса.) И каждый объект Ruby может иметь переменные экземпляра, поэтому объекты класса также могут иметь переменные экземпляра.

Проблема заключается в том, что переменные экземпляра объектов класса не ведут себя так, как обычно вы хотите, чтобы переменные класса вели себя. Обычно вы хотите, чтобы переменная класса, определенная в суперклассе, была разделена с ее подклассами, но это не так, как работают переменные экземпляра - подкласс имеет свой собственный объект класса, и этот объект класса имеет свои собственные переменные экземпляра. Таким образом, они ввели отдельные переменные класса с поведением, которое вы, скорее всего, захотите.

Другими словами, переменные экземпляра класса представляют собой случай аварии конструкции Ruby. Вы, вероятно, не должны их использовать, если вы не знаете, что они именно то, что вы ищете.

+0

так переменная класса как статическая переменная в Java? –

Смежные вопросы