I read "When do Ruby instance variables get set?" but I'm of two minds when to use class instance variables.
Class variables are shared by all objects of a class, Instance variables belong to one object. There's not much room left to use class instance variables if we have class variables.
Could someone explain the difference between these two and when to use them?
Here's a code 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 understand now, Class Instance Variables are not passed along the inheritance chain!
I believe the main (only?) different is inheritance:
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.
As others said, class variables are shared between a given class and its subclasses. Class instance variables belong to exactly one class; its subclasses are separate.
Why does this behavior exist? Well, everything in Ruby is an object—even classes. That means that each class has an object of the class
Class
(or rather, a subclass ofClass
) corresponding to it. (When you sayclass Foo
, you're really declaring a constantFoo
and assigning a class object to it.) And every Ruby object can have instance variables, so class objects can have instance variables, too.The trouble is, instance variables on class objects don't really behave the way you usually want class variables to behave. You usually want a class variable defined in a superclass to be shared with its subclasses, but that's not how instance variables work—the subclass has its own class object, and that class object has its own instance variables. So they introduced separate class variables with the behavior you're more likely to want.
In other words, class instance variables are sort of an accident of Ruby's design. You probably shouldn't use them unless you specifically know they're what you're looking for.
So as you know a class variable are variables that are available to a specific class and the syntax looks like so:
However, you'll rarely use class variables in real-world applications because you can accomplish the same through local or instance variables. Nothing is wrong if you use class variables, but its not commonly utilized by most developers. In fact, the local and instance variables are likely to make up more than 98 percent of variables in your application, so it's a good idea to be familiar with them.
As the name suggests, instance variables are available to a specific instance. There is a specific syntax to set instance variables, you need to use the @ sign to define a variable. Here is a real-world example from my own work:
In this code, you can see that there is an instance variable called @portfolio_items. This variable is created in the method index and is not available to other methods in the file. Now, why did I not just make this a local variable since it's not available to other methods in the class?
The reason for this is because Rails is structured in such a way that the view and controller files are wired to communicate with each other, so this instance variable @portfolio_items can be accessed in the associated view file like so:
Now, @portfolio_items are available in the singular for the view page only because I made it an instance variable in the controller file.
Instance variable on a class:
Class variable:
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:
And then in action:
#class instance variable are available only to class method and not to instance methods whereas class variable are avilable to both instance methods and class methods. Also the class instance variables are lost in inheritance chain whereas class variables are not.