"Self" confusion

Can someone explain why the following produces different results? In
another question I wrote that by default, programs run inside the
definition-space of Object, but now I think that I was wrong:

class Yoghurt
def self.a
“yoghurt self”
end
def Yoghurt.a
“yoghurt”
end

p Yoghurt.a
p self.a
end

def self.a
“object self”
end
def Object.a
“object”
end

p Object.a
p self.a

------------------------Output:
“yoghurt self”
“yoghurt self”
“object”
“object self”

Leslie V. wrote:

end
“object”

Really? Because I get:

“yoghurt”
“yoghurt”
“object”
“object self”

:slight_smile:

I thought the top-level stuff rain inside an instance of Object?

Try:

p Object.class #=> Class, naturally
p self.class #=> Object

class A
p self.class #=> Class
end

a = A.new

class<<a
p self.class #=> Class
end

So, if we were really in the definition space of Object, then self.class
would be class, not Object.

-Justin

Justin C. wrote:

“yoghurt”
def Object.a
“object self”
I thought the top-level stuff rain inside an instance of Object?
a = A.new

I meant to add some "I think"s and "I guess"s in there somewhere.

-Justin

On 7/25/06, Justin C. [email protected] wrote:

I thought the top-level stuff rain inside an instance of Object?

Now I am fully confused! How do you define methods inside an instance
of an object?
Using .class_eval? Is that what IRB does at the top
level?

Les

end
I am not Ruby expert, but isn’t Yogurt.a and self.a the same thing?
Then the last one simply overwrites the preceding one.

From this I think that
Object.a and self.a should act similary, don’t they?

Now I am fully confused! How do you define methods inside an instance
of an object?

obj = Object.new
=> #Object:0x3551a4

class << obj
def foo
“foo”
end
end
=> nil

obj.foo
=> “foo”

obj.singleton_methods
=> [“foo”]

Regards,
Rimantas

See comments in the code.

class Yoghurt
def self.a # Here self is the Yoghurt class. This defines a method
on the Yoghurt class
“yoghurt self”
end
def Yoghurt.a # This does exactly the same as self.a, just another
way of doing it.

This overwrites the previous version, which is quite legit in Ruby

"yoghurt"

end

p Yoghurt.a
p self.a
end

def self.a

This defines a on self, which is an instance of Object.

“object self”
end
def Object.a

This defines a on the Object class

“object”
end
p Object.a
p self.

And the output I’d expect is:

On 7/26/06, Rimantas L. [email protected] wrote:

Now I am fully confused! How do you define methods inside an instance
of an object?

Just like that :wink: Pick up a copy of Programming Ruby, it’s got a
better explanation than I could come up with.

Basically when you do:
x = Object.new
def x.foo
‘bar’
end

you’re added a singleton class on to x that contains the instance
method foo. Only x can use this, no other Object instance will have
it.

So likewise when you’re in an instance of Object, as ruby scripts
start out in, self.foo is creating an instance method in the singleton
class of the Object instance.

Schüle Daniel wrote:

end
Daniel

Yes it is exactly the same if you are inside the definition of the
class. That is why I was trying to say that the top level of Ruby cannot
be inside the definition of Object, because then

p self.a

would be the same as

p Object.a

but it isn’t, because we are not in a class definition. However,

def self.a
“Hi from self”
end

is the same as

def a
“Hi from self again”
end

and the latter will overwrite the first, as we are defining methods for
this instance of the class.

From Pickaxe 1:

" At the top level, we’re executing code in the context of some
predefined object. When we define methods, we’re actually creating
(private) singleton methods for this object. Instance variables belong
to this object. And because we’re in the context of |Object|, we can use
all of |Object|'s methods (including those mixed-in from |Kernel|) in
function form. This explains why we can call |Kernel| methods such as
|puts| at the top level (and indeed throughout Ruby): these methods are
part of every object."

-Justin

Well, in both cases, it refers to an object. When you are in the
top-level of a class definition, “self” actually refers to the class
object. That is to say, the instance of Class your new class
definition creates.

class Foo
puts self
puts self.class
end

=> Foo
=> Class

So using self adds a method to the object “self”, which happens to be
an instance of class. ie. class methods.

Oh, sorry, I slightly mis-read. Yes, you probably know most of that.
Anyway, “new” is an instance method of the new object created, so I
see what you are saying.

…oops

Thanks everybody, this really helps!
So top level is an Object singleton referenced through ‘self’.

I think I get it.

Part of my problem was that ‘self’ refers to the enclosing class when
using def self.x, but within the new function, self refers to an
object. Very interesting.

Les