About top-level method

S

Sam Sungshik Kong

Hello!

I'm reading a book named "Teach yourself Ruby".
In chapter 2, it says that top-level methods are Object's private instance
methods.
But my test shows different results.

In irb, I tested it like the following.

def my_f
p "my_f"
end

Object.my_f #=> print "my_f"
obj = Object.new
obj.my_f #=> print "my_f"

Then, my_f is an instance method, and a class method as well?

Can anyone help me understand it?

kong
 
J

Joel VanderWerf

Sam said:
Hello!

I'm reading a book named "Teach yourself Ruby".
In chapter 2, it says that top-level methods are Object's private instance
methods.
But my test shows different results.

In irb, I tested it like the following.

def my_f
p "my_f"
end

Object.my_f #=> print "my_f"
obj = Object.new
obj.my_f #=> print "my_f"

Then, my_f is an instance method, and a class method as well?

Only in irb, as I understand. Try it using 'ruby file.rb', and you'll
get the private method exception. Irb is not quite ruby ;)
 
J

Julian Fondren

In irb, I tested it like the following.
def my_f
p "my_f"
end

Object.my_f #=> print "my_f"
obj = Object.new
obj.my_f #=> print "my_f"

Well, you tested it in irb.
Consider:

julian@tenacity test $ cat >> priv-test.rb
def my_f
p "my_f"
end

Object.my_f
obj = Object.new
obj.my_f
julian@tenacity test $ ruby -w priv-test.rb
priv-test.rb:5: private method `my_f' called for Object:Class (NoMethodError)
 
G

gabriele renzi

Then, my_f is an instance method, and a class method as well?

Can anyone help me understand it?

well, you ahould consider that:
=> true

everything is_a object including Object as well.
 
S

Sean O'Dell

Hello!

I'm reading a book named "Teach yourself Ruby".
In chapter 2, it says that top-level methods are Object's private instance
methods.
But my test shows different results.

In irb, I tested it like the following.

def my_f
p "my_f"
end

Object.my_f #=> print "my_f"
obj = Object.new
obj.my_f #=> print "my_f"

Then, my_f is an instance method, and a class method as well?

Can anyone help me understand it?

The Object class is the base of every other class, and is itself an instance
of class Class.

Sean O'Dell
 
M

Mauricio Fernández

The Object class is the base of every other class, and is itself an instance
of class Class.

irb can sometimes mislead you:

$ ruby
def foo; 1 end
Object.foo
-:2: private method `foo' called for Object:Class (NoMethodError)

--
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

(It is an old Debian tradition to leave at least twice a year ...)
-- Sven Rudolph
 
S

Sam Sungshik Kong

Hi, Sean!

Thank you for the reply.
You helped me understand half of the issue.
As Object is a superclass of all classes (except for Object),
if I add a method to Object, the metaclass of Object will have it too.
That enlightened me a lot.

However, there's one more thing to solve.
When I define a method at top-level,
it's Object's private instance method.
So it can't be used like receiver.method.
obj.my_f #-> Error because my_f is private.
Object.my_f #->Error because my_f is private.

The question is why irb ignores the error?
Is it intentional or a bug?

I also appreciate all other replies.

kong
 
S

Sean O'Dell

Hi, Sean!

Thank you for the reply.
You helped me understand half of the issue.
As Object is a superclass of all classes (except for Object),
if I add a method to Object, the metaclass of Object will have it too.
That enlightened me a lot.

However, there's one more thing to solve.
When I define a method at top-level,
it's Object's private instance method.
So it can't be used like receiver.method.
obj.my_f #-> Error because my_f is private.
Object.my_f #->Error because my_f is private.

The question is why irb ignores the error?
Is it intentional or a bug?

I also appreciate all other replies.

My guess is irb ignores the private flag to allow you to test what you wish
from irb. It's really just a debugging environment, so it makes sense to
disable private flags.

Sean O'Dell
 
L

Lennon Day-Reynolds

I don't think irb is ignoring the "private" flag -- you're actually
inside the private scope of an Object instance whenever you're
inputting data at the prompt. That means methods are defined on the
current class; i.e., Object. It's easy to test:

(at irb prompt:)

def test
puts self.id
end

test
=> -542341874 (or similar)

puts self.id
=> -542341874 (or similar)

To show that all 'private' flags are not being ignored, try the
following (again, in irb):

class Foo
private
def test
puts "testing"
end
end

f = Foo.new
f.test
=> NoMethodError: private method `foo' called for #<A:0xbf50fcf4>
from (irb):16

Hope that helps,

Lennon
 
S

Sam Sungshik Kong

Hi, Lennon!

If I understand correctly, one can't call a private method via object name
(receiver).
Private methods can be called only with self.

So the following code will cause an error (at the top level).

def foo #->this is a private instance method of Object
...
end

obj = Object.new

obj.foo #->Error, but in irb, it's ok.

Best explanation so far is that irb makes an exception for debugging
purpose.


While trying to find the answer, I met more confusing statements in the
Programming Ruby (Classes and Objects chapter).

<snip>
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.
</snip>

Is the above explanation correct?
Do I create a singleton method if I define a method at the top level?

I'm getting more and more confused...
Before I started Ruby, I thought I understood OOP concepts very clearly
(with Java, C#, even Python).
But Ruby puts me in a deep confusion with singleton methods, somewhat
different concept of private/protected accessibility, metaclass, etc...
But I like Ruby very much.
I'm sure that if I overcome the difficulties, I will be a better
programmer...:)

kong
 
S

Sean O'Dell

Hi, Lennon!

If I understand correctly, one can't call a private method via object name
(receiver).
Private methods can be called only with self.

So the following code will cause an error (at the top level).

def foo #->this is a private instance method of Object
...
end

obj = Object.new

obj.foo #->Error, but in irb, it's ok.

Best explanation so far is that irb makes an exception for debugging
purpose.


While trying to find the answer, I met more confusing statements in the
Programming Ruby (Classes and Objects chapter).

<snip>
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.
</snip>

Is the above explanation correct?
Do I create a singleton method if I define a method at the top level?

I'm getting more and more confused...
Before I started Ruby, I thought I understood OOP concepts very clearly
(with Java, C#, even Python).
But Ruby puts me in a deep confusion with singleton methods, somewhat
different concept of private/protected accessibility, metaclass, etc...
But I like Ruby very much.
I'm sure that if I overcome the difficulties, I will be a better
programmer...:)

Ruby implements global space in a unique way. It secretly puts everything in
the top level into the class definition of Object. Try this experiment:

@@testvar = "asd"

def testvar
@@testvar
end

h = Hash.new

p h.send:)testvar)

Both testvar and @@testvar are part of the class definition of Object, and
Object is the base of all other objects, so that last line of code prints out
"asd".

Ruby treats everything at the top-level as though it were wrapped by the class
definition of Object:

class Object
# top-level code here
end


Sean O'Dell
 
J

Jeff Mitchell

--- Sam Sungshik Kong said:
Hi, Lennon!

If I understand correctly, one can't call a private method via object name
(receiver).
Private methods can be called only with self.

You can also call a private method via send:

class A
private
def f
99
end
end

puts A.new.send:)f)
# => 99
So the following code will cause an error (at the top level).

def foo #->this is a private instance method of Object
...
end

obj = Object.new

obj.foo #->Error, but in irb, it's ok.

Best explanation so far is that irb makes an exception for debugging
purpose.


While trying to find the answer, I met more confusing statements in the
Programming Ruby (Classes and Objects chapter).

<snip>
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.
</snip>

Is the above explanation correct?
Do I create a singleton method if I define a method at the top level?

I would say the book explantion is not correct,

# courtesy dblack
module Kernel
def singleton_class
class << self
self
end
end
end

def naked
88
end

puts self.class == Object
# => true
puts self.class.private_instance_methods.include?("naked")
# => true
puts self.singleton_class.private_instance_methods.include?("naked")
# => true

If the method was added only to the singleton class, as the book asserts, then
first "include?" check would give false.





__________________________________
Do you Yahoo!?
New and Improved Yahoo! Mail - Send 10MB messages!
http://promotions.yahoo.com/new_mail
 
H

Hal Fulton

Sam said:
If I understand correctly, one can't call a private method via object name
(receiver).
Private methods can be called only with self.

So the following code will cause an error (at the top level).

def foo #->this is a private instance method of Object
...
end

obj = Object.new

obj.foo #->Error, but in irb, it's ok.

Best explanation so far is that irb makes an exception for debugging
purpose.

No, I don't think that's quite right. My guess would be that when
you're in an irb session, you're not really at the top level.

Imagine something like:

obj.instance_eval do
# User commands...
end

In other words, I think it's a side effect of the way irb works --
neither a bug nor a feature as such, and not a special exception
deliberately built in.

That's just my impression. I haven't proved it.


Hal
 
J

James Britt

Sam said:
I'm getting more and more confused...
Before I started Ruby, I thought I understood OOP concepts very clearly
(with Java, C#, even Python).
But Ruby puts me in a deep confusion with singleton methods, somewhat
different concept of private/protected accessibility, metaclass, etc...


Java and (to the best of my knowledge) C# have a particular philosophy
of OO that differs from Ruby (and probably Python).

My understanding of OO tends to center on the notion of sending messages
to receivers; the receiver may or may not know how to handle the
message. The receiver may have originated from a class derived from
one or more other classes, but, once created, may have acquire new or
altered behavior not found in any of the base class(es). Messages sent,
and methods implemented in the receiver, should not have to map to one
another; how an object responds to a message is up to that particular
object. The default behavior for handling unknown messages tends to be
an exception, but that should be left to the object (i.e., the
developer), not hard-coded into the language.

By analogy, think of a web site. Pages generally map to specific URLs.
Many web sites simply toss back a 500 or 404 when given an unknown
request, but the smarter sites know how to map all URLs to something
useful. Now imagine if a web site was operationally prevented from
handling unknown URLs. Or if a user could not even *try* to request a
page without knowing the full, correct URL in advance. (The
statically-typed Web?)

This view of OO runs counter to statically typed languages such as Java
and C#, where behavior tends to be set in stone early on, and object
behavior is defined by method invocation rather than message handling.

The idea that one object may be able to respond to messages that another
object of the same class cannot is alien in Java, but normal in Ruby.

Likewise, the idea that classes and objects are malleable during runtime
is largely foreign in Java, but an essential fact of Ruby.

I'm not sure how much any of this helps you with your actual problem :);
I'm not even sure how accurate it is*. Getting your head around Ruby
is may be an adventure if you're coming from Java/C#.

There's also a good take on what constitutes various flavors of OO on
Paul Graham's site [0]. (There's lot's of other good stuff on his site,
BTW. I particularly like his comments on Arc and OO [1])



James

* I'm trusting somebody here will promptly correct me where I'm wrong.
But no flamewars, please.

[0] http://www.paulgraham.com/reesoo.html
[1] http://www.paulgraham.com/noop.html
 
S

Sam Sungshik Kong

James, thanks you so much for your elaborate answer.
Yes, there's a lot to learn yet...:)
Ruby is a new world and a pleansant challenge to me.
Paradigm shifting is always difficult but eventually worthwhile.

I'll check out the links.

Thanks again.

kong

James Britt said:
Sam said:
I'm getting more and more confused...
Before I started Ruby, I thought I understood OOP concepts very clearly
(with Java, C#, even Python).
But Ruby puts me in a deep confusion with singleton methods, somewhat
different concept of private/protected accessibility, metaclass, etc...


Java and (to the best of my knowledge) C# have a particular philosophy
of OO that differs from Ruby (and probably Python).

My understanding of OO tends to center on the notion of sending messages
to receivers; the receiver may or may not know how to handle the
message. The receiver may have originated from a class derived from
one or more other classes, but, once created, may have acquire new or
altered behavior not found in any of the base class(es). Messages sent,
and methods implemented in the receiver, should not have to map to one
another; how an object responds to a message is up to that particular
object. The default behavior for handling unknown messages tends to be
an exception, but that should be left to the object (i.e., the
developer), not hard-coded into the language.

By analogy, think of a web site. Pages generally map to specific URLs.
Many web sites simply toss back a 500 or 404 when given an unknown
request, but the smarter sites know how to map all URLs to something
useful. Now imagine if a web site was operationally prevented from
handling unknown URLs. Or if a user could not even *try* to request a
page without knowing the full, correct URL in advance. (The
statically-typed Web?)

This view of OO runs counter to statically typed languages such as Java
and C#, where behavior tends to be set in stone early on, and object
behavior is defined by method invocation rather than message handling.

The idea that one object may be able to respond to messages that another
object of the same class cannot is alien in Java, but normal in Ruby.

Likewise, the idea that classes and objects are malleable during runtime
is largely foreign in Java, but an essential fact of Ruby.

I'm not sure how much any of this helps you with your actual problem :);
I'm not even sure how accurate it is*. Getting your head around Ruby
is may be an adventure if you're coming from Java/C#.

There's also a good take on what constitutes various flavors of OO on
Paul Graham's site [0]. (There's lot's of other good stuff on his site,
BTW. I particularly like his comments on Arc and OO [1])



James

* I'm trusting somebody here will promptly correct me where I'm wrong.
But no flamewars, please.

[0] http://www.paulgraham.com/reesoo.html
[1] http://www.paulgraham.com/noop.html
 

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,709
Latest member
AustinMudi

Latest Threads

Top