Top-level

L

Lucas Holland

Hello everyone!

I'm currently diving a bit deeper into Ruby and I've already asked this
question in the IRC (the folks there have been great I think I'm getting
it 50%). The question's about top-level methods:

Let's take puts as an example. Puts is inside of the Kernel module,
which gets mixed into the Object class. So essentially, it's a private
method of Object. When I call puts, I don't specify a receiver, so self
is assumed (I think so). In this case self refers to main, an instance
of Object, automatically created. So, I'm really calling main.puts. main
is an instance of Object, so why is it able to call private methods of
Object?


Help would be greatly appreciated!

Lucas
 
R

Robert Klemme

I'm currently diving a bit deeper into Ruby and I've already asked this
question in the IRC (the folks there have been great I think I'm getting
it 50%). The question's about top-level methods:

Let's take puts as an example. Puts is inside of the Kernel module,
which gets mixed into the Object class. So essentially, it's a private
method of Object. When I call puts, I don't specify a receiver, so self
is assumed (I think so).
Correct.

In this case self refers to main, an instance
of Object, automatically created. So, I'm really calling main.puts. main
is an instance of Object, so why is it able to call private methods of
Object?

Um, you explained it already: "puts" is an *instance* method of Object.
And since "main" is an instance of Object or one of its subclasses
(all classes are subclasses of Object!) it has method "puts". Basically
the method is only defined private in order to enforce a more function
like invocation:

irb(main):001:0> self.puts "foo"
NoMethodError: private method `puts' called for main:Object
from (irb):1
from :0
irb(main):002:0> puts "foo"
foo
=> nil
irb(main):003:0>

Kind regards

robert
 
R

Rick DeNatale

Hello everyone!

I'm currently diving a bit deeper into Ruby and I've already asked this
question in the IRC (the folks there have been great I think I'm getting
it 50%). The question's about top-level methods:

Let's take puts as an example. Puts is inside of the Kernel module,
which gets mixed into the Object class. So essentially, it's a private
method of Object.
Yes

When I call puts, I don't specify a receiver, so self
is assumed (I think so).
Yes

In this case self refers to main, an instance
of Object, automatically created.

Yes, well it's created when ruby starts up.
So, I'm really calling main.puts. main
is an instance of Object, so why is it able to call private methods of
Object?

You're calling puts in the context of the top-level object. In other
words self is the top-level object in code which is outside any class
or method definitions. The method puts is a private instance method,
so any Object can invoke it as long as the receiver is implicitly
'self':

irb(main):001:0> p self
main
=> nil
irb(main):002:0> puts "foo"
foo
=> nil
irb(main):003:0> self.puts "foo"
NoMethodError: private method `puts' called for main:Object
from (irb):3

Note that the ruby enforces private methods is that you can't
explictily specify a receiver, even self.

Note that IRB treats methods defined at the top level a little
differently, in that they are public rather than private:

irb(main):004:0> def bar
irb(main):005:1> puts "bar"
irb(main):006:1> nil
irb(main):007:1> end
=> nil
irb(main):008:0> bar
bar
=> nil
irb(main):009:0> self.bar
bar
=> nil

But
$ ruby -e'def bar;puts "bar";nil;end;bar;self.bar'
bar
-e:1: private method `bar' called for main:Object (NoMethodError)

Help would be greatly appreciated!

HTH
 
L

Lucas Holland

Robert said:
Um, you explained it already: "puts" is an *instance* method of Object.
And since "main" is an instance of Object or one of its subclasses
(all classes are subclasses of Object!) it has method "puts". Basically
the method is only defined private in order to enforce a more function
like invocation:

irb(main):001:0> self.puts "foo"
NoMethodError: private method `puts' called for main:Object
from (irb):1
from :0
irb(main):002:0> puts "foo"
foo
=> nil
irb(main):003:0>

Kind regards

robert

Hey, it's me again (this time I'm logged in ;-) ). I understand that
puts is a private instance method of Object and that thus, all instances
of Object have the method. I also understand that I can only call
private methods if the receiver is self (by not specifying the
receiver). So, in this instance, that's the case. When I however create
a class like so:

class MyClass
private
def test
puts "hello, world"
end
public
def pub
test
end
end

I am able to call the test method because of the implicit receiver,
self. In this case, however, self refers to the class MyClass (which is
an instance of Class, as far as I know). But MyClass is an instance of
Class, not of itself, so why can it suddenly call *instance* methods of
itself?

Thanks in advance,

Lucas
 
B

Brian Candler

receiver). So, in this instance, that's the case. When I however create
a class like so:

class MyClass
private
def test
puts "hello, world"
end
public
def pub
test
end
end

I am able to call the test method because of the implicit receiver,
self. In this case, however, self refers to the class MyClass (which is
an instance of Class, as far as I know).

No. Inside your 'test' method, which is an instance method of MyClass, self
refers to an object which is one particular instance of MyClass.

That is, you can't run it like this:

MyClass.pub

Rather, you have to do

MyClass.new.pub

(the receiver of the message is an *instance* of MyClass that you've
created)

Outside of 'def test', self does indeed refer to the class.

class MyClass
p self # self is 'MyClass'
def test
p self # self is an instance of MyClass
end
end
 
L

Lucas Holland

Brian said:
No. Inside your 'test' method, which is an instance method of MyClass,
self
refers to an object which is one particular instance of MyClass.

That is, you can't run it like this:

MyClass.pub

Rather, you have to do

MyClass.new.pub

(the receiver of the message is an *instance* of MyClass that you've
created)

Outside of 'def test', self does indeed refer to the class.

class MyClass
p self # self is 'MyClass'
def test
p self # self is an instance of MyClass
end
end

Ah, I see. Okay, so I can call puts like a 'standalone function' because
of the following: When I run a Ruby script, an object called 'main' is
instanciated. It's an instance of the Object class. The Object class
includes puts via a mixin from the Kernel module. It's thus like a
private instance method of Object.

When I call puts, I don't specify a receiver. That's why Ruby takes self
as the receiver. At the top level, self refers to the main object. So my
call is basically main.puts

puts is a *private* instance method of Object, so why can I call it from
an instance (main being the instance in this case)?

Lucas
 
D

David A. Black

Hi --

Ah, I see. Okay, so I can call puts like a 'standalone function' because
of the following: When I run a Ruby script, an object called 'main' is
instanciated. It's an instance of the Object class. The Object class
includes puts via a mixin from the Kernel module. It's thus like a
private instance method of Object.

When I call puts, I don't specify a receiver. That's why Ruby takes self
as the receiver. At the top level, self refers to the main object. So my
call is basically main.puts

Except that Ruby makes a pretty huge distinction between meth and
obj.meth (presence or absence of explicit receiver), namely: private
methods have to be called without an explicit receiver.

class C
def x
puts "x"
end
private :x

def y
x # no explicit receiver
end
end

c = C.new
c.y # the call to x takes place inside y, where self is c
c.x # explicit receiver; Ruby won't let you do it
puts is a *private* instance method of Object, so why can I call it from
an instance (main being the instance in this case)?

See above. Private doesn't mean you can never call the method :) It
just means that you have to call it without an explicit receiver,
which essentially translates into: you can call private methods on
self (because you can call methods on self without an explicit
receiver).


David

--
Upcoming Rails training by Ruby Power and Light:
Four-day Intro to Intermediate
May 8-11, 2007
Edison, NJ
http://www.rubypal.com/events/05082007
 
L

Lucas Holland

Okay, so I can call puts because I am calling it on self (and self
refers to main, doesn't it?)?

Lucas
 
B

Brian Candler

Ah, I see. Okay, so I can call puts like a 'standalone function' because
of the following: When I run a Ruby script, an object called 'main' is
instanciated. It's an instance of the Object class. The Object class
includes puts via a mixin from the Kernel module. It's thus like a
private instance method of Object.

When I call puts, I don't specify a receiver. That's why Ruby takes self
as the receiver. At the top level, self refers to the main object. So my
call is basically main.puts

Roughly. Except you can't actually call it that way, because it's private.
puts is a *private* instance method of Object, so why can I call it from
an instance (main being the instance in this case)?

'Private' means it can *only* be called on self, and only using the implicit
form (where you don't specify a receiver).

HTH,

Brian.
 
R

Rick DeNatale

Okay, so I can call puts because I am calling it on self (and self
refers to main, doesn't it?)?

Yes, although the fact that self in this case refers to main is pretty
much irrelevant.

In general, self always refers to SOME object, in top-level code that
object is the top-level object or main.

In an instance method, self is the instance which received the message.

In a class method, self is the class, but Class is a subclass of
Object so classes also inherit the methods of Object, including the
(private) methods defined by Kernel which is included by Object. The
only time you can't if if a class has specifically undefined the
method.

I'll refrain from talking about BasicObject in ruby1.9 unless asked.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,705
Latest member
Stefkari24

Latest Threads

Top