What are Ruby variables preceded with double at signs (@@
)? My understanding of a variable preceded with an at sign is that it is an instance variable, like this in PHP:
PHP version
class Person {
public $name;
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
Ruby equivalent
class Person
def set_name(name)
@name = name
end
def get_name()
@name
end
end
What does the double at sign @@
mean, and how does it differ from a single at sign?
A variable prefixed with
@
is an instance variable, while one prefixed with@@
is a class variable. Check out the following example; its output is in the comments at the end of theputs
lines:You can see that
@@shared
is shared between the classes; setting the value in an instance of one changes the value for all other instances of that class and even child classes, where a variable named@shared
, with one@
, would not be.[Update]
As Phrogz mentions in the comments, it's a common idiom in Ruby to track class-level data with an instance variable on the class itself. This can be a tricky subject to wrap your mind around, and there is plenty of additional reading on the subject, but think about it as modifying the
Class
class, but only the instance of theClass
class you're working with. An example:I included the
Square
example (which outputsnil
) to demonstrate that this may not behave 100% as you expect; the article I linked above has plenty of additional information on the subject.Also keep in mind that, as with most data, you should be extremely careful with class variables in a multithreaded environment, as per dmarkow's comment.
@@
denotes a class variable, i.e. it can be inherited.This means that if you create a subclass of that class, it will inherit the variable. So if you have a class
Vehicle
with the class variable@@number_of_wheels
then if you create aclass Car < Vehicle
then it too will have the class variable@@number_of_wheels
@
- Instance variable of a class@@
- Class variable, also called as static variable in some casesA class variable is a variable that is shared amongst all instances of a class. This means that only one variable value exists for all objects instantiated from this class. If one object instance changes the value of the variable, that new value will essentially change for all other object instances.
Another way of thinking of thinking of class variables is as global variables within the context of a single class. Class variables are declared by prefixing the variable name with two
@
characters (@@
). Class variables must be initialized at creation timeThe answers are partially correct because @@ is actually a class variable which is per class hierarchy meaning it is shared by a class, its instances and its descendant classes and their instances.
This will output
So there is only one same @@variable for Person, Student and Graduate classes and all class and instance methods of these classes refer to the same variable.
There is another way of defining a class variable which is defined on a class object (Remember that each class is actually an instance of something which is actually the Class class but it is another story). You use @ notation instead of @@ but you can't access these variables from instance methods. You need to have class method wrappers.
Here, @people is single per class instead of class hierarchy because it is actually a variable stored on each class instance. This is the output:
One important difference is that, you cannot access these class variables (or class instance variables you can say) directly from instance methods because @people in an instance method would refer to an instance variable of that specific instance of the Person or Student or Graduate classes.
So while other answers correctly state that @myvariable (with single @ notation) is always an instance variable, it doesn't necessarily mean that it is not a single shared variable for all instances of that class.
@ and @@ in modules also work differently when a class extends or includes that module.
So given
Then you get the outputs below shown as comments
So use @@ in modules for variables you want common to all their uses, and use @ in modules for variables you want separate for every use context.