Everything is an object (in ruby).

Less than a week since it began, many interesting discussions have been floating around ruby on rails course mailing thread. A great one in particular is the discussion on the OO-ness of ruby taken from the conversation between Victoria Pocladova and Raul Parolari. Consider this:

“Ruby is an object oriented language and an object has a well-defined interface that specifies the behavior of the object in a manner that is independent of its implementation. This interface defines the collection of services that can be invoked by other objects.” - http://c2.com/cgi/wiki?ObjectOriented

Main.rb and Object

The next questions become how would you describe the behavior “main.rb”? You can have blocks of code within the main class, and no method containing this code. How is this code exactly invoked by another objects, or by the compiler itself when the main class is executed? And since I don’t have any methods in the main class, where does the “puts” command come from? Does main class get special treatment like void main() method in Java?

It does seem a bit contradiction to the earlier paragraph describing the OO concept of ruby. Raul Parolari, my course adviser colleague, offers a great explanation of this.

First, let’s try creating a main.rb file and execute this line of code.

puts self #main
puts self.class #Object

‘main’ is like the backstop of Ruby program. It is the farthest back you can fall; but it is also the current object as soon as your programs starts up. By the way, ‘puts’ is in Object? no, it is a method of module Kernel. But wait a moment; didn’t we say that ’self’ class was Object? how can we call ‘puts’ on an Object instance? Because… every object’s search path includes the Kernel module; and how is that?

Kernel module

That’s because the class Object mixes in Kernel, and every object’s Class has Object as an ancestor. Now try this

puts self.class.ancestors #[Object, Kernel]
puts 'string'.class.ancestors # [String, Enumerable, Comparable, Object, Kernel]

Again, we see Kernel lurking at the back.

puts

The next thing we can investigate is if ‘puts’ is actually a member of Object.

puts self.class.private_methods.include?('puts') #true
puts Object.private_methods.include?('puts') #true

Oh wait? Didn’t I just say that ‘puts’ is a method of module Kernel? If you trace EVERY class in ruby, you’ll see Object and Kernel at the top of inheritance hierarchy. Now let’s try to interogate Object class again and keep out inherited members.

puts Object.private_methods(false).include?('puts') # false
puts Kernel.class.private_methods.include?('puts') #true

Gotcha! As you can see, ‘puts’ is actually a member of Kernel module that Object benefits from. And since every class in ruby is an Object, they all benefit from the work of Kernel as well.

As the lead adviser for this program, I’m astound to see this kind of thing in the discussion thread myself. The understanding of core concept highlights beauty and benefits of the language.

Teera on July 25th 2008 in Software Development, Ruby

One Response to “Everything is an object (in ruby).”

  1. TEERA 2.0 » Module and Mixin revisited responded on 29 Jul 2008 at 9:45 pm #

    […] In the last post, I showed an example of ‘puts’ method. ‘puts’ is available to all Object in Ruby. ‘puts’ exists in Kernel module, and Kernel is mixed into Object class. Now since everything in ruby is an Object, they also automatically have access to ‘puts’ in Kernel module. puts “string”.class.ancestors # [String,Enumerable,Comparable,Object,Kernel] […]

Trackback URI | Comments RSS

Leave a Reply