Ruby Method Like 'Self' That Refers to Instance

Ruby method like `self` that refers to instance

self always refers to an instance, but a class is itself an instance of Class. In certain contexts self will refer to such an instance.

class Hello
# We are inside the body of the class, so `self`
# refers to the current instance of `Class`
p self

def foo
# We are inside an instance method, so `self`
# refers to the current instance of `Hello`
return self
end

# This defines a class method, since `self` refers to `Hello`
def self.bar
return self
end
end

h = Hello.new
p h.foo
p Hello.bar

Output:

Hello
#<Hello:0x7ffa68338190>
Hello

How to use Ruby's self keyword

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.

Does self ALWAYS refer to the current instance in an instance method definition?

Generally, yes, though there are some metaprogramming methods that can do some strange things with self - for instance, Object#instance_eval allows you to pass a block to be evaluated in the context of another instance. In that case, the self within the block is that of the other instance, like so:

class Foo
end

class Bar
def wacky
puts self.class #"Bar"
Foo.new.instance_eval do
puts self.class #"Foo"
end
end
end

Without a careful reading, you might be tempted to think that the self within the block refers to the Bar instance, but this is not so.

So you see, for most purposes, you can assume self is the self that is bound when entering a method. Although you have the ability to pass blocks around that get a different binding, self doesn't get re-bound "by accident" in Ruby. For more interesting reading, you might look at the ruby Binding class' documentation.

When do I need to use self.instance_method vs instance_method alone?

There are a few differences between self.foo(...) and foo(...), but they're mostly equivalent.

Privacy

private methods can only be called via foo directly, and never with an explicit receiver. So if foo is marked private, then you have to call it without self.

class Example

private def foo(x)
x + 1
end

def bar
foo # Works fine
self.foo # Error: foo is private
end

end

Shadowing

If you have a local variable called foo in the current function, then writing foo without arguments will reference the local variable instead

class Example

def foo(*args)
puts "Hello :)"
end

def bar
foo = 100 # Just an ordinary variable; no relation to the above method
foo # This refers to the local variable called "foo"
self.foo # This calls the method foo() with no arguments
foo(1) # This calls the method foo() with one argument
self.foo(1) # Equivalent to the above; calls with one argument
end

def baz
foo # There's no local variable called "foo", so this calls the method
end

end

Assignment

If the method you're talking about is an assignment method (i.e. ends in =), then it must always be called with an explicit receiver

class Example

def foo=(value)
puts "Assigning foo = #{value}"
end

def bar
foo = 0 # This creates a new local variable called foo and assigns to it
self.foo = 0 # Calls foo= on self
end

end

In Ruby, inside a class method, is self the class or an instance?

That is correct. self inside a class method is the class itself. (And also inside the class definition, such as the self in def self.coolpost.)

You can easily test these tidbits with irb:

class Foo
def self.bar
puts self.inspect
end
end

Foo.bar # => Foo

Is there a way to create methods just for the instance of a Ruby class from inside that instance?

You need to grab a reference to the instance's singleton class, the class that holds all the instance specific stuff, and define the method on it. In ruby 1.8, it looks a little messy. (if you find a cleaner solution let me know!)

Ruby 1.8

class Example
def initialize(test='hey')
singleton = class << self; self end
singleton.send :define_method, :say_hello, lambda { test }
end
end

Ruby 1.9 however, provides a much easier way in.

Ruby 1.9

class Example
def initialize(test='hey')
define_singleton_method :say_hello, lambda { test }
end
end

How does ruby tell the difference between instance method and class method definition?

In a method body, self refers to the receiver. In lines 3..4 of the following, once the receiver is determined to be a User instance (by the def greeting syntax), self refers to that instance.

class User
def greeting
puts "Hi, #{name}" # method body
puts "Hi, #{self.name}" # method body
end
end

In a class body, self refers to the class. In lines 2, 4, 8, 10 of the following, the class is User, so def self.greeting is the same as def User.greeting.

class User
def self.greeting # class body
# ...
end # class body
end

class User
def greeting # class body
# ...
end # class body
end

But I actually think your real issue is not what self means, but rather what "an omitted receiver" means, in different contexts.

In method-calling syntax, an omitted receiver stands for self. So the following two are the same:

name
self.name

In method-defining syntax, an omitted receiver stands for "any instance of the class". So the following two are not the same:

def User.greeting; ... end
def greeting; ... end

When you define an instance method, there is no explicit way to express "any instance of the class", so actually omission is mandatory.

What is the 'self' keyword doing exactly in this Class method?

self is the class Restaurant. def self.method is how you implement a method on the class itself rather than an instance of the class. Restaurant.filter_by_city(...) rather than Restaurant.new.filter_by_city(...).

self changes in Ruby depending on context. Within a method, self is the object the method was called on.

Within the class Restaurant block, and outside of any method, self is the Restaurant object which is a Class object. Everything is an object in Ruby. Everything.

You can also do this by declaring a block where the class is the instance.

class << self
def filter_by_city(restaurants, city)
restaurants.select { |restaurant| restaurant.city == city }
end
end

Normally you'd use this syntax if you have a lot of class methods.

See Self in Ruby: A Comprehensive Overview for more.



Related Topics



Leave a reply



Submit