====== Class Instance Variables vs Class Variables ======
Class Variables in Ruby are unlike class variables in many other programming variables. If you change the value of a class variable, all class variables in the inheritance chain are changed to this new value too. This is explained by Martin Fowler, [[http://www.martinfowler.com/bliki/ClassInstanceVariable.html|right here]].
The "solution" is to use class instance variables, as is explained [[http://railstips.org/2006/11/18/class-and-instance-variables-in-ruby|here]], by John Nunemaker. In his post, John also provides a module to have the class instance value carry over as a kind of constant to a subclass.
My own solution to have inheritable default values for class instance variables is this:
class Polygon
class << self
attr_writer :sides
def sides
@sides || 8
end
end
end
All subclasses of ''Polygon'' will share the default value of 8 sides, but each subclass can also easily be given its own number of sides.
class Triangle < Polygon
@sides = 3
end
class Octogon < Polygon; end
This does what you'd expect:
>> Polygon.sides
=> 8
>> Triangle.sides
=> 3
>> Octogon.sides
=> 8
The new value for class ''Triangle'' is not carried down the inheritance chain, though. Let's say you have a class ''FantasyShape'':
class FantasyShape < Triangle; end
What happens now is this:
>> Triangle.sides
=> 3
>> FantasyShape.sides
=> 8
To fix this, you'd have to override the class method ''sides'' for ''FantasyShape'':
class FantasyShape < Triangle
def self.sides
@sides || superclass.sides
end
end
Or better yet, start the superclass lookup in the top of the inheritance chain:
class Polygon
class << self
attr_writer :sides
def sides
@sides || ((superclass.respond_to?('sides')) ? superclass.sides : 8)
end
end
end
Now we can simplify the code for class ''FantasyShape'' back to:
class FantasyShape < Triangle; end
And voilĂ :
>> Triangle.sides
=> 3
>> FantasyShape.sides
=> 3
Ruby rocks!