Class variables are never really required. But the reason isn't that they're shared state. I mean, it's good to avoid shared state where you can, but that's not the real problem here.
The reason they're recommended against is, as shown in that article, they are really confusing. In particular, a class's class variables are shared by its subclasses and instances of its subclasses. For example:
class Parent
end
class Child1 < Parent
@@class_var = "Child1's"
end
class Child2 < Parent
@@class_var = "Child2's"
end
With this code, Child1 and its instances will all see a class variable named @@class_var
with the value "Child1's"
and Child2 and its instances will all see a class variable named @@class_var
with the value "Child2's"
. But suppose later on we reopen Parent and write this:
class Parent
@@class_var = "Parent's"
end
Now Parent and the instances it creates will all see a class variable named @@class_var
with the value "Parent's"
. But that's not all. Now that the parent class has this variable, Child1 and Child2 suddenly share the variable, so all of the @@class_var
s have the value "Parent's"
. And if you reassign the variable in Child1, it's still shared, so all of the classes get updated. How confusing!
Instead of class variables, you can just use instance variables of the class, like this:
class Parent
@class_var = "Parent's"
def self.class_var
@class_var
end
end
class Child1 < Parent
@class_var = "Child1's"
end
class Child2 < Parent
@class_var = "Child2's"
end
Now, Parent.class_var
will return "Parent's", Child1.class_var
will return "Child1's" and Child2.class_var
will return "Child2's" — just like you expect.