Friday, August 17, 2007

Self in Ruby.

What is all about “self” in ruby.
An object can send a message in three ways:
1) It can send a message to the other object
2) It can send a message to no object, which implicitly sends message to itself
3) It can send a message to explicitly itself

Example for case-I
-------------------
class Upcaser
def some_behavior_on(a_string)
a_string.upcase
end
end
Upcaser.new.some_behavior_on("foo")
=> "FOO"

Example for case-II
--------------------
class Bouncer
def some_behavior
another_behavior
end
def another_behavior
"another_behavior used"
end
end
Bouncer.new.some_behavior
=> "another_behavior used"

Example for case-III
---------------------
class AnotherBouncer
def some_behavior
self.another_behavior
end
def another_behavior
"another_behavior used"
end
end
AnotherBouncer.new.some_behavior
=> "another_behavior used"

“self” is a variable that always names the object itself. It is not widely common in scripts, But it is mainly used in the following cases
Suppose you have a class that stores an integer and can do nothing but add one to it:
Self in Ruby. When you search for online code in ruby language, emphatically you will encounter with the key word self exploited in many places. Inquisitive to know more on self?

Here we go. Let’s have some basic background information on object to object interface in ruby. An object can send message to other object in 3 ways.
1) It can send a message to the other object.
2) It can send a message to no object, which implicitly sends message to itself
3) It can send a message to explicitly itself

Take an example for

Case-I
------
class Upcaser
def some_behavior_on(a_string)
a_string.upcase
end
end
Upcaser.new.some_behavior_on("maruthi")
=> "MARUTHI"

Case-II
--------
class Bouncer
def some_behavior
another_behavior
end
def another_behavior
"another_behavior used"
end
end
Bouncer.new.some_behavior
=> "another_behavior used"

Case-III
---------
class AnotherBouncer
def some_behavior
self.another_behavior
end
def another_behavior
"another_behavior used" -----> (1)
end
end
AnotherBouncer.new.some_behavior
=> "another_behavior used"

Let’s emphasize on case-III, In this case we have used “self”.

No we can define self; Self is an variable that always names the object itself. Of course it’s not widely common scripts. But it plays the vital role in the following cases.

Suppose you have a class that stores an integer and can do nothing but add one to it:

class Adder
attr_reader :value
def initialize
@value = 0
end
def add1
@value += 1
end
end

(@value += 1 is a shorthand way of writing @value = @value + 1.)

Further suppose you wanted to add three to one of these objects. You’d have to do this:
a = Adder.new
=> #

a.add1
=> 1

a.add1
=> 2

a.add1
=> 3

That’s rather verbose. But suppose add1 returned self instead of the result of the addition:

class Adder
def add1
@value += 1
self
end
end

That allows this more succinct form:

Adder.new.add1.add1.add1.value
=> 3

Some method names are also special words in the Ruby language. For example, when Ruby sees class, how does it know whether you are sending the class message to self or starting to define a new class?

The answer is that it doesn’t:

class Informer
def return_your_class
class
end
end
SyntaxError: compile error

You can prevent the error with self:

class Informer
def return_your_class
self.class
end
end
=> nil Informer.new.return_your_class
=> Informer

When you leave parentheses off messages with no arguments, what you have looks just like a local variable. Consider the following:

class M
def start
1
end
def multiplier
start = start -->(1)
start * 30
end
end

At (1), is the start to the right of the equal sign the local variable created on the left, or does it represent sending the message start to self? Let’s find out:

M.new.multiplier
NoMethodError: undefined method ‘*' for nil:NilClass in ‘multiplier'

Both uses of the word “start” refer to a variable, though the exact sequence of events is a little hard to figure out:

1. Ruby encounters the line at (1) It’s an assignment to a name never been seen before. Ruby creates the new local variable and gives it the value nil.
2. Ruby now looks at the right side of the assignment. There’s a reference to. . .what? Ruby guesses it’s the local variable start. So Ruby assigns start the value it already has, nil.
3. The next line multiplies nil by 30.
The problem can be avoided by sending the message to self. . .

start = self.start
. . . or by using parentheses:
start = start()

It’s a good idea to get in the habit of doing one or the other. I favor using self, for no good reason.

No comments: