What is the difference between a class instance variable and a class variable in Ruby?
I understand that class variables (@@var
) are shared across all instances of a class, while instance variables (@var
) belong to a single object. However, where do class instance variables fit in, given that we already have class variables?
Could someone clarify their differences and when to use each?
Here’s an example:
class S
@@k = 23
@s = 15
def self.s
@s
end
def self.k
@@k
end
end
p S.s # 15
p S.k # 23
I also realized that Ruby class variables (@@var
) are inherited, while class instance variables (@var
) are not. Could someone explain the best use cases for both?
Basic Explanation of Class Variables @@var :
The key difference is that class variables (@@var) are shared among the class and all of its subclasses. This means that modifying a class variable in a subclass affects all instances of the parent class as well.
For example:
class Parent
@@shared_var = 10
end
class Child < Parent
@@shared_var = 20
end
p Parent.class_variable_get(:@@shared_var) # => 20
p Child.class_variable_get(:@@shared_var) # => 20
Here, changing @@shared_var in Child also affects Parent, which may lead to unintended consequences."
Introducing Class Instance Variables @var
: However, class instance variables (@var) behave differently—they belong to the class itself, not to instances of the class, and they are not shared with subclasses.
Here’s an example using class instance variables:
class Parent
@not_shared = 10
def self.not_shared
@not_shared
end
end
class Child < Parent
@not_shared = 20
end
p Parent.not_shared # => 10
p Child.not_shared # => 20
Unlike @@var
, @var
is independent in each class. Each class has its own version of @not_shared
, making it safer for maintaining encapsulated state."
To summarize:
Use @var (class instance variables) when you want class-specific state that is not inherited by subclasses. This is useful for per-class configuration settings or internal state management.
For example, ActiveRecord models often use class instance variables for configuration:
class Model
@config = {}
def self.config
@config
end
end
class User < Model
@config = { table_name: "users" }
end
p Model.config # => {}
p User.config # => {:table_name=>"users"}
This ensures that Model and User each maintain independent configurations rather than sharing the same mutable @@var state."