my idea is to create a community wiki for people that come from a java
background because reading a lot of explanations, I couldn't comprehend anything until I actually tried a couple of things and the pieces of the puzzle started to find their places. But I first need to make sure I'm getting it right. Coming from such background it was very confusing for me to find out that @variable
may mean 2 very different things.
Here is an example:
class Test
@ins = "gah"
def self.ins
puts @ins
end
def initialize()
@ins = "wtf?"
end
def ins2
puts @ins
end
end
As far as I understand, the first @ins
is an instance variable of the object representing the class Test
. The second @ins
is an instance variable in an object of class Test
.
Now things start to make some sense to me. Here a couple of examples:
[14] pry(main)> test.ins2
wtf?
We are calling a method of an object and it returns the object's instance variable.
[15] pry(main)> test.ins
NoMethodError: undefined method `ins' for #<Test:0x000000017d9348 @ins="wtf?">
We are trying to call a class method through an object, this method is of the class so we are getting NoMethodError
[16] pry(main)> Test.ins
gah
We are calling a class method so it properly sees the instance variable of the class object.
[17] pry(main)> Test.ins2
NoMethodError: undefined method `ins2' for Test:Class
We are calling an object method through the class which is incorrect so throwing NoMethodError
.
All of the above was performed with ruby 2.0. So what am I asking?
- Am I getting it right?
- Am I getting the ruby terminology correct?
- Any real usage of class instance variables that make sense in a properly designed app? Or are these simply the better @@class variables?
No, it doesn't. Classes are objects just like any other object. They can have instance variables just like any other object. They can have instance methods just like any other object. In fact, unlike Java, which has three different kinds of "methods" (instance methods, static methods and constructors), in Ruby, there is exactly one kind of method: instance methods.
The beauty of having classes being objects is precisely that
@variable
always means exactly the same thing.There is no such thing as a class instance variable: it's just a normal instance variable like any other. The object happens to be an instance of
Class
, but that doesn't change the nature of the instance variable. An instance variable of an object of classString
is not a string instance variable, it's just an instance variable. Likewise, an instance variable of an object of classClass
is just an instance variable.There is no such thing as a class method: it's just a normal singleton method of an object which happens to be an instance of
Class
. (Acually, there's no such thing as a singleton method either: it's just a normal instance method of the object's singleton class.)Note: Rubyists may use the term "class method" in casual conversation. But that doesn't mean that class methods actually exist, it only means that "instance method of the class object's singleton class" is a mouthful. The important thing is: because classes are objects, they work exactly like all other objects. They can have instance methods (defined in class
Class
or inherited fromModule
,Object
,Kernel
orBasicObject
), they can have "singleton methods" (which really are instance methods of their respective singleton classes), they can have instance variables.They can also have class variables (
@@variables
) … those are weird. Ignore them :-)First, to understand instance variables, one need to know this - classes are objects.
All classes are instances of
Class
(read the doc) which inherits fromObject
. That's why classes are objects.Then, every instance variables(ids marked with
@
, like@ins
) are defined inself
.When
self
is a class, they are instance variables of classes(class instance variables). Whenself
is a object, they are instance variables of objects(instance variables).In different code scopes, the
self
represents different things.Everything looks right to me.
A class variable will be passed down through inheritance while an instance variable on a class will not. (src: Ruby class instance variable vs. class variable)
As far as design goes, I tend to prefer avoiding class variables altogether (I'd rather use a singleton), but if I had to choose one I would probably choose a class variable over a class instance variable to avoid confusion.