Reputation: 118271
To see who is playing the role of self
in nested methods
, I tried the below code:
def test
p "#{self}"
def show
p "#{self}"
end
end
# => nil
As an effect, I got the two objects below:
Object.new.test
"#<Object:0x00000002212d78>"
# => nil
Object.new.test.show
"#<Object:0x00000002205330>" #<~~~ this is self understood
"" #<~~~ how this one came?
# => ""
But from the encoded numbers, I couldn't understand which class those objects belong to. And I tried the code below and got the respective class
names.
Object.new.test.class
"#<Object:0x000000021ff3b8>"
# => NilClass
Object.new.test.show.class
"#<Object:0x000000020660b0>"
""
# => String
So can anyone help me to understand the concept of how the above code produced those class
names?
EDIT
Here I tried to ask my question on more specific way:
def test
p "First level # => #{self}"
def show
p "Second level # => #{self}"
end
end
# => nil
Object.new.test.show
"First level # => #<Object:0x000000014a77b0>"
"Second level # => "
# => "Second level # => "
Object.new.test.show.class
"First level # => #<Object:0x0000000130ef70>"
"Second level # => "
# => String
Why the p "Second level # => #{self}"
statement self
has ""
value?
Upvotes: 2
Views: 401
Reputation: 118271
We all know that - self inside a method is always the object on which the method was called
. So let's try and examine the truthfulness of that.
Let's see who is default self
from the below code first of all:
m=self
# => main
m.class
# => Object
Okay, the default self
is the object of Object
class.
Just written the below code in more simplified way, from the description mentioned code,to highlight on the concept.
def test
p self.class
def show
p self.class
end
end
# => nil
Keeping in mind self inside a method is always the object on which the method was called
called only test
as below.
test
Object
# => nil
Yes, Object
has been returned,on which the test
has been called,that means the above statement is true.
test.show
Object
NilClass
# => NilClass
Calling to test
also returns nil
due to the block def show;p self.class;end
.Now nil
is an object of NilClass
. Thus show
method has been called on NilClass
object. As result self
is NilClass
. Again the above statement holds.
With the above concept trying to reach to the actual goal with tiny steps:
def test
p "1. # => #{self}"
def show
p "2. # => #{self}"
end
end
# => nil
test
"1. # => main" #<~~ main is an object of class Object,on which test was called from IRB.
# => nil
test.show
"1. # => main"
"2. # => " #<~~ nil("" means nil.to_s) is an object of Nilclass,on which show was called from IRB.
# => "2. # => "
Upvotes: 0
Reputation: 336
Object.new.test.show calls the show method in the Object.new.test object.
Object.new.test returns nil (as p returns nil), but at the same time it adds the definition of the show method to Object class.
As nil is of the class NilClass, which is a subclass of Object, nil has now show as a method, so you can actually call show in nil.
When you do Object.new.test.show is equivalent then to do
nil.show
When, within show, you do p "#{self}", you are actually printing nil.to_s
nil.to_s is ""
That explains that mysterious "" you see.
Upvotes: 3
Reputation: 20878
Try this :
class FooBar
def foo
puts self.class
puts self
def bar
puts self.class
puts self
end
bar
end
end
FooBar.new.foo
I got :
FooBar
#<FooBar:0x007fc413849818>
FooBar
#<FooBar:0x007fc413849818>
You got different results since you allocated different objects.
self
returns the object where the method is defined in, even if it's a nested method.
Upvotes: 1
Reputation: 10349
Try using: self.class.to_s
. SO wants me to enter extra characters, so [:
Upvotes: 0
Reputation: 31077
It's rather straightforward:
def show
p "#{self}"
end
returns nil
, i.e. the def
part, this is why the test
method returns a nil
object, an instance of the NilClass
. Within the show
method, you are doing p "#{self}"
which will return a string object which is an instance of the String
class.
Upvotes: 1