ruby - Instance variable: self vs @

ID : 20298

viewed : 20

Tags : rubyselfinstance-variablesruby

Top 5 Answer for ruby - Instance variable: self vs @

vote vote

97

Writing @age directly accesses the instance variable @age. Writing self.age tells the object to send itself the message age, which will usually return the instance variable @age — but could do any number of other things depending on how the age method is implemented in a given subclass. For example, you might have a MiddleAgedSocialite class that always reports its age 10 years younger than it actually is. Or more practically, a PersistentPerson class might lazily read that data from a persistent store, cache all its persistent data in a hash.

vote vote

89

The difference is that it is isolating the use of the method from the implementation of it. If the implementation of the property were to change -- say to keep the birthdate and then calculate age based on the difference in time between now and the birthdate -- then the code depending on the method doesn't need to change. If it used the property directly, then the change would need to propagate to other areas of the code. In this sense, using the property directly is more fragile than using the class-provided interface to it.

vote vote

74

Be warned when you inherit a class from Struct.new which is a neat way to generate an intializer (How to generate initializer in Ruby?)

class Node < Struct.new(:value)     def initialize(value)         @value = value     end     def show()         p @value         p self.value # or `p value`     end end   n = Node.new(30) n.show() 

will return

30 nil 

However, when you remove the initializer, it will return

nil 30 

With the class definition

class Node2     attr_accessor :value     def initialize(value)         @value = value     end     def show()         p @value         p self.value     end end 

You should provide the constructor.

n2 = Node2.new(30) n2.show() 

will return

30 30 
vote vote

61

The first answer is entirely correct, but as a relative newbie it wasn't immediately clear to me what it implied (sending messages to self? uh huh...). I think that a short example will help:

class CrazyAccessors   def bar=(val)     @bar = val - 20 # sets @bar to (input - 20)   end   def bar     @bar   end    def baz=(value)     self.bar = value # goes through `bar=` method, so @bar = (50 - 20)   end    def quux=(value)     @bar = value     # sets @bar directly to 50   end end  obj  = CrazyAccessors.new obj.baz = 50 obj.bar  # => 30 obj.quux = 50 obj.bar  # => 50 
vote vote

58

There isn't any difference. I suspect that it was done just for the documentary value of seeing self.age and other_person.age near each other.

I suppose that use does allow for an actual getter to be written in the future, which might do something more complex than just return an instance variable, and in that case the method would not need to change.

But that's an unlikely abstraction to worry about, after all, if the implementation of the object changed it's reasonable to change other methods, at some point a simple reference within the object itself is perfectly reasonable.

In any case, abstraction of the age property still doesn't explain the explicit use of self, as just plain age would also have invoked the accessor.

Top 3 video Explaining ruby - Instance variable: self vs @

Related QUESTION?