Ruby class instance variable vs. class variable Ruby class instance variable vs. class variable ruby ruby

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] 


Source

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.