Difference between foo
and @foo
Instance variables
Instance variables are defined within instance methods, and their names begin with @. Their value is only accessible within the specific object on which it was set. In other words, when we modify the value of an instance variable, the change only applies to that particular instance. Unlike local variables which are only available within the method where they were defined, instance variables are accessible by all methods within the object (instance methods of the class). Instance variables are the most commonly used type of variable in Ruby classes.
class Car
attr_reader :color
def set_color(color_receiverd_as_argument)
@color = color_receiverd_as_argument
end
end
car1 = Car.new
car1.color # Output: => nil
car1.set_color "black"
car1.color # Output: => "black"
car2 = Car.new
car2.set_color "silver"
car2.color # Output: => "silver"
In the example above, notice that:
- Trying to access an instance variable before it's initialized will not raise an exception. Its default value is nil.
- Changing the value of the color variable in one instance of the Car class does not affect the value of the same variable in the other instances.
Local variables
A local variable within a class is like any other local variable in Ruby. It is only accessible within the exact scope on which it's created. If defined within a method, it is only available inside that method.
class Car
def initialize
wheels = 4
end
def print_wheels
print wheels
end
end
c = Car.new
c.print_wheels # Output: NameError: undefined local variable or method `wheels'…
The self keyword
The self keyword is always available, and it points to the current object. In Ruby, all method calls consist of a message sent to a receiver. In other words, all methods are invoked on an object. The object on which the method is called is the receiver, and the method is the message. If we call "foo".upcase, the "foo" object is the receiver and upcase is the message. If we don't specify an object (a receiver) when calling a method, it is implicitly called on the self object.
Self keyword at class level
When used within a class but outside any instance methods, self refers to the class itself.
class Foo
@@self_at_class_level = self
def initialize
puts "self at class level is #{@@self_at_class_level}"
end
end
f = Foo.new # Output: self at class level is Foo
Self keyword at instance methods
When inside an instance method, the self keyword refers to that specific instance. In other words, it refers to the object where it was called.
class Meditation
def initialize
puts "self within an instance method is #{self}"
end
end
zazen = Meditation.new # Output: self within an instance method is #<Meditation:0x00000000ab2b38>
Notice that #<Meditation:0x00000000ab2b38>
is a string representation of the zazen object, which is an instance of the Meditation class.