Are these the same?

I'm wondering about the difference between writing something like

@x = ...
and
self.x = ...

from within a class. Are they the same thing? To be more concrete, I have given a fuller example below:

class Foo
   def bar
     self.x = 1
   end
end

class Foo
   def bar
     @x = 1
   end
end

Lowell

Lowell Kirsh wrote:

I'm wondering about the difference between writing something like

@x = ...
and
self.x = ...

from within a class. Are they the same thing? To be more concrete, I have given a fuller example below:

They are different, but the degree of difference depends on the context. The "@x =" construct is ruby's built-in way of assigning to an instance variable in the current object ("self"). It does not invoke any methods. The "self.x =" construct is a special syntax for calling the method whose name is "x=" on the object denoted by "self". This method may or may not assign to the instance variable @x, and it may do other things in addition to assigning to @x. For instance, you might also execute some debugging code:

class Foo
   def x=(val)
     puts "setting x = #{val.inspect}"
     @x = val
   end
end

Or you might not assign to @x at all. For example:

class Square
   def width=(val)
     self.height = val
   end
   def height=(val)
     @height = val
   end
end

Since width and height must be equal, there's no need to store them separately. But users of the Square class don't have to know that. Some people call this the "uniform access principle".

Lowell Kirsh wrote:

I'm wondering about the difference between writing something like

@x = ...
and
self.x = ...

from within a class. Are they the same thing?

Not necessarily the same.

@x = ... # assigns an instance variable
self.x = ... # invokes a method called x= (which doesn't
                # exist in your example.

Now, having said they're different... if you add

   attr_accessor :x

then they are more the same.

Bear in mind that instance variables are accessed from the
"outside world" only via methods.

And when you say self.x within a class, you are basically
accessing it "from the outside" even though you are inside
the class (dumb analogy: You're in your house, and you
reach outside a window and then reach into the window next
to it "from outside").

Also bear in mind that if you (manually) define a method x=,
you *could* define it in a stupid or misleading way (just
as you *could* give misleading names to all your variables
and methods):

     def x=(val)
       puts "Ha, fooled you! I'm setting @y to 123!"
       @y = 123 # and not even using val
     end

Hope this helps...

Hal

Thank you both. Things are much clearer now :slight_smile:

Lowell Kirsh wrote:

···

I'm wondering about the difference between writing something like

@x = ...
and
self.x = ...

from within a class. Are they the same thing? To be more concrete, I have given a fuller example below:

class Foo
  def bar
    self.x = 1
  end
end

class Foo
  def bar
    @x = 1
  end
end

Lowell