Weird Ruby Class Variable
If you had programmed for some time, you would have come across class Variables. Most Programming language has it. It is a variable that belongs to the class itself. Taking the definition from Wikipedia
Language like C# and Java uses static keywords to define it. But this article is a Ruby(Beautiful Language) article, so let’s see how it is implemented and its weird quirks.
The Two Ways To Diamond
To show the two ways to implement class variables in ruby, we will implement a class that creates instances and stores how many instances are created from the class. We will also add a class method that prints the number.
1. Class Instance Variable (@)
code is as follow:
class Fruit
@instance_count = 0
def initialize
self.class.increment_instance_count
end
def self.instance_count
@instance_count
end
def self.increment_instance_count
@instance_count += 1
end
end
Fruit.new
Fruit.new
Fruit.new
Fruit.new
p Fruit.instance_count #4Let’s take a while to explain this code. First, a very important key to note in this code is “in ruby, everything is an object”. Objects have instance variables that are private to them.
In the second line, we initialize the class instance variable (not just an instance variable but a class instance) “@instance_count” to zero. Since instance variables are private, we need a function to expose this variable. Hence, we created the “increment_instance_count” class method to increment the instance variable. And “instance_count” to output the instance variable. Lastly, we call the class “increment_instance_count” method in the “initialize” method because it is always called when a new instance is created.
Get Unegbu Kingsley’s stories in your inbox
Join Medium for free to get updates from this writer.
Importantly, something to take note of is the “self.class” in the initialize call.
self.class.increment_instance_countThis is important as “initialize” is in the context of the instance variable. That is self here refers to the instance. So we need the class of the instance and then call “increment_instance_count”.
2. Class Variable (@@)
code is as follow:
class Fruit
@@instance_count = 0
def initialize
@@instance_count += 1
end
def self.instance_count
@@instance_count
end
end
Fruit.new
Fruit.new
Fruit.new
Fruit.new
p Fruit.instance_count #4This way, we remove some of the complexities of the earlier version. We are using “@@instance_count” which is not private to the class. It is accessible to the instance, hence, we don’t need the “increment_instance_count” method from the earlier version to increment. We can increment it as shown in the initialize method.
def initialize
@@instance_count += 1
endThe Weird Quirk
From the two versions, the second way seems to be the way to go for its elegance and simplicity. But there is a caveat. There is something you need to have in mind while using @@.
It is shared across ancestors line
This means that any member of the ancestor has access to change the value and query the value.
From our example, we have a class “Fruit” if call the ancestor as follows
p Fruit.ancestors #[Fruit, Object, Kernel, BasicObject]We get an array. If any of these objects in the array edit the value of “@@instance_count”, it will reflect and skew our program.
Currently, none of the objects is changing the value, so our program runs as expected. However, it is worth knowing that ancestors can update/edit the values of class variables.
CONCLUSION
Ruby is an interesting language that has multiple ways of doing different things. I showed a little hidden fact about class variables that will enable you to choose the right tools while designing your software system.
As always thanks for your time and happy coding.







