Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby classes: initialize self vs. @variable

Tags:

ruby

Can someone explain the difference between initializing "self" and having @variables when defining classes?

Here's an example

class Child < Parent
  def initialize(self, stuff):
    self.stuff = stuff
    super()
  end
end

So in this case, wouldn't I be able to replace self.stuff with @stuff? What's the difference? Also, the super() just means whatever is in the Parent initialize method the Child should just inherit it right?

like image 215
bigpotato Avatar asked Aug 23 '12 18:08

bigpotato


People also ask

Why do we use self in Ruby?

The keyword self in Ruby enables you to access to the current object — the object that is receiving the current message. The word self can be used in the definition of a class method to tell Ruby that the method is for the self, which is in this case the class.

What does self mean in Ruby?

self is a special variable that points to the object that "owns" the currently executing code. Ruby uses self everwhere: For instance variables: @myvar. For method and constant lookup. When defining methods, classes and modules.

Do you need to initialize variables in Ruby?

Ruby Class Variables Class variables begin with @@ and must be initialized before they can be used in method definitions. Referencing an uninitialized class variable produces an error.


2 Answers

In general, no, self.stuff = stuff and @stuff = stuff are different. The former makes a method call to stuff= on the object, whereas the latter directly sets an instance variable. The former invokes a method which may be public (unless specifically declared private in the class), whereas the latter is always setting a private instance variable.

Usually, they look the same because it is common to define attr_accessor :stuff on classes. attr_accessor is roughly equivalent to the following:

def stuff
  @stuff
end

def stuff=(s)
  @stuff = s
end

So in that case, they are functionally identical. However, it is possible to define the public interface to allow for different results and side-effects, which would make those two "assignments" clearly different:

def stuff
  @stuff_called += 1    # Keeps track of how often this is called, a side effect
  return @stuff
end

def stuff=(s)
  if s.nil?             # Validation, or other side effect. This is not triggered when setting the instance variable directly
    raise "Argument should not be nil"
  end
  @stuff = s
end
like image 190
Platinum Azure Avatar answered Sep 20 '22 04:09

Platinum Azure


You actually can't use self.stuff= unless you specifically create an attr_writer for modifying that value.

In fact, these are equivalent:

class Child
  attr_writer :stuff
end

class Child
  def stuff=(val)
    @stuff = val
  end
end

It is more common to use an attr_writer if that is the functionality you want, rather than the explicit method. But you will often use an explicit method if you want to perform extra error checking or change the way the assignment works.

To your question of when to use @stuff = and when to use self.stuff =, I would use the former if you only have simple assignments and if your class is simple, and would move towards the latter if your requirements might become more complicated. There are many other reasons too, but it's more a matter of style than anything else.

like image 38
Peter Avatar answered Sep 21 '22 04:09

Peter