Ruby class instance variable vs. class variable
Instance variable on a class:
class Parent @things = [] def self.things @things end def things self.class.things endendclass Child < Parent @things = []endParent.things << :carChild.things << :dollmom = Parent.newdad = Parent.newp Parent.things #=> [:car]p Child.things #=> [:doll]p mom.things #=> [:car]p dad.things #=> [:car]
Class variable:
class Parent @@things = [] def self.things @@things end def things @@things endendclass Child < ParentendParent.things << :carChild.things << :dollp Parent.things #=> [:car,:doll]p Child.things #=> [:car,:doll]mom = Parent.newdad = Parent.newson1 = Child.newson2 = Child.newdaughter = Child.new[ mom, dad, son1, son2, daughter ].each{ |person| p person.things }#=> [:car, :doll]#=> [:car, :doll]#=> [:car, :doll]#=> [:car, :doll]#=> [:car, :doll]
With an instance variable on a class (not on an instance of that class) you can store something common to that class without having sub-classes automatically also get them (and vice-versa). With class variables, you have the convenience of not having to write self.class
from an instance object, and (when desirable) you also get automatic sharing throughout the class hierarchy.
Merging these together into a single example that also covers instance variables on instances:
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 endendclass Child < Parent @shared_things = []end
And then in action:
mama = Parent.newpapa = Parent.newjoey = Child.newsuzy = Child.newParent.family_things << :housepapa.family_things << :vacuummama.shared_things << :carpapa.shared_things << :blenderpapa.my_things << :quadcopterjoey.my_things << :bikesuzy.my_things << :dolljoey.shared_things << :puzzlesuzy.shared_things << :blocksp 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]
Availability to instance methods
- Class instance variables are available only to class methods and not to instance methods.
- Class variables are available to both instance methods and class methods.
Inheritability
- Class instance variables are lost in the inheritance chain.
- Class variables are not.
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 endendVars.class_methodputs "see the difference"obj = Vars.newobj.instance_methodclass VarsChild < VarsendVarsChild.class_method
I believe the main (only?) different is inheritance:
class T < Sendp T.k=> 23S.k = 24p T.k=> 24p T.s=> nil
Class variables are shared by all "class instances" (i.e. subclasses), whereas class instance variables are specific to only that class. But if you never intend to extend your class, the difference is purely academic.