69

From what I understand about self, it refers to the current instance of the class.

Isn't this the default behaviour at all times anyways? For example, isn't

self.var_one = method(args)

equivalent to

var_one = method(args) 

If so, what is the use of self?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
ankit
  • 3,328
  • 3
  • 26
  • 39

4 Answers4

127

There are several important uses, most of which are basically to disambiguate between instance methods, class methods, and variables.

First, this is the best way to define class methods:

class Foo
  def self.bar
    "class method bar"
  end

  def bar
    "instance method bar"
  end
end

Foo.bar  #returns "class method bar"

foo = Foo.new
foo.bar #returns "instance method bar"

Also, within instance methods self refers to the instance, within class methods it refers to the class, and it can always be used to distinguish from local variables.

class Bar
  def self.foo
    "foo!"
  end

  def baz
    "baz!"
  end

  def self.success
    foo #looks for variable foo, doesn't find one, looks for class method foo, finds it, returns "foo!"
  end

  def self.fail
    baz #looks for variable baz, doesn't find one, looks for class method baz, doesn't find one, raises exception
  end

  def instance_success
    baz #looks for variable baz, doesn't find one, looks for instance method baz, finds it, returns "baz!"
  end

  def instance_fail
    foo #looks for variable foo, doesn't find one, looks for instance method foo, doesn't find one, raises exception
  end

  def local_variable
    baz = "is my favorite method"
    baz #looks for variable baz, finds it, returns "is my favorite method"
  end

  def disambiguate
    baz = " is my favorite method"
    self.baz + baz #looks for instance method baz, finds it, looks for local variable baz, finds it, returns "baz! is my favorite method"
  end
end

So, in the end, you can avoid using self in many cases, but it's often helpful to use it to make sure that you don't inadvertently create naming conflicts later on. Sometimes those can create bugs that are very hard to find. In the end it's often a matter of personal style.


As noted in the comments, one more really important thing:

In a class, if you have a method like this:

def bar=(string)
  ...
end

And in another method you call:

def other_method
  bar = "abcd"
end

It isn't going to call your bar= method, it's going to create a local variable bar. So, in this case you use self to tell Ruby not to create a local variable:

def other_method
  self.bar = "abcd"
end

The same thing applies if you want to take an argument with the name of a method:

def example
  ...
end

def other_thing(example)
  self.example(example)
end

If you left off self Ruby would assume you meant the local variable with the same name.

So, in general, self in method names is used to distinguish between class and instance variables, and everywhere else you use it when Ruby needs help distinguishing between method calls and local variables or local variable assignment.

I hope that makes sense.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Andrew
  • 42,517
  • 51
  • 181
  • 281
  • 4
    This is a more thorough answer, except that it doesn't include the assignment caveat. There is also a good blog article on the usages: http://www.jimmycuadra.com/posts/self-in-ruby which includes, specifically, assignment. You can't call an assignment method without using self (as noted in the first answer). – mltsy Mar 11 '13 at 19:54
  • 2
    Very helpful for Java guys =) – Fernando Jun 21 '13 at 14:56
  • 2
    probably, it's better to outline the principle that "you can only access class variable/method inside a class method" – fengd Jun 25 '13 at 05:23
  • @fengd Of-course you can call class variable/method from instance method using self.class.class_method " class Person def self.class_method 'golbal variable' end def show self.class.class_method end end person = Person.new puts person.show – Engr. Hasanuzzaman Sumon Apr 27 '15 at 08:52
60

In most cases self.foo is indeed redundant because you can just write foo for the same effect, but in this case it is not and the self is required.

var_one = method(args) will create a local variable called var_one, it will not call any method or do anything else to self.

self.var_one = method(args) will call the method var_one= on self with the argument method(args).

Another case where the use of self is non-optional would be if you want to pass it as an argument to a method, i.e. some_method(self) - you can't do that without the self keyword.

sepp2k
  • 363,768
  • 54
  • 674
  • 675
  • I'm sorry I'm confused. How can `var_one=` be a method? I meant for `var_one` to be a variable, and assign the result of the method named `method` to that variable. – ankit Jul 12 '11 at 19:52
  • 1
    @Ankit: It can be a method by being a method. Sorry if that's a bit of a non-answer, but I don't really know how else to answer that. If you want `var_one` to be a local variable, putting `self.` in front of it is wrong and will not do what you want. – sepp2k Jul 12 '11 at 20:30
  • 5
    @Ankit Soni: If you send any message to `self` (e.g., `self.foo`) it is calling the `foo` method of your class. `var_one=` is just a setter method. If you want `var_one` to be a variable, you must not use `self` (which is only useful for calling methods). If you're looking for instance variables then you simply prefix an identifier with `@` (e.g., `@var_one`) – cam Jul 12 '11 at 20:30
  • 1
    OK I understand how `var_one=` is the setter method. Now ,even in this case, wouldnt `var_one=` also call the same setter method of that same instance of the object as `self.var_one=`? – ankit Jul 12 '11 at 20:41
  • Wait are you saying that `var = "bla"` exists only as a setter method in ruby? i.e there is no assignment operator, and this writing `a = b` is only a convenient way of writing `a.set(b)`? – ankit Jul 12 '11 at 20:46
  • 1
    @Ankit: No. If you write `var = "bla"` this will always create a local variable and never invoke a setter method. If you write `foo.var = "bla"`, it will call the setter method `var=` on `foo`. So to invoke the `var=` setter method on `self`, you need to write `self.var = "bla"`. Writing `var = "bla"` will *not* suffice as it will simply create a local variable. – sepp2k Jul 12 '11 at 21:10
  • @sepp2k So writing `var = "bla"` will make a local variable `var` and set it to `"bla"`. Isn't that what my setter method would do for me anyways? Sorry I'm asking so many questions about this by the way, I'm just trying to figure this out and be done with it. – ankit Jul 13 '11 at 12:54
  • 4
    @Ankit: Your setter method will do what ever you define it to do. However it will almost certainly not create a local variable named `var`, as that variable, being local, would only live inside that setter method and thus have no effect. If you defined the setter method using `attr_accessor`, what it will do is create an *instance variable* called `@var`. So in that specific case `@var = "foo"` and `self.var = "foo"` would do the same thing. However `var = "foo"` would not. – sepp2k Jul 13 '11 at 13:32
4

Here's an example:

def run miles
  self.miles = miles
end

In this case self will help. In most cases self is redundant.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Sohan
  • 3,757
  • 2
  • 24
  • 24
4

One other use of self is to declare class methods (similar to static methods in Java).

class foo
 def self.bar
  #do class related stuff here
 end
end

That being said, you could also have used def foo.bar instead for the method signature.

brayne
  • 1,355
  • 2
  • 16
  • 27