tags:

views:

447

answers:

3

How is it that Ruby allows a class access methods outside of the class implicitly?

Example:

class Candy
    def land
     homer
    end
end

def homer
    puts "Hello"
end

Candy.new.land #Outputs Hello
+18  A: 

The definition of the "homer" method is adding the method to the Object class. It is not defining a free function.

Class Candy implicitly inherits from Object, and so has access to the methods in Object. When you call "homer" in the "land" method, the method resolution can't find a definition in the current class, goes to the super class, finds the method you have added to Object, and calls it.

janm
See my clarification below... It is defined on the Kernel module, not the Object class.
nertzy
+3  A: 

Technically, the definition of the homer method is actually on the Kernel module which is mixed into Object, not on Object directly. So when homer is not a local variable or an instance method defined on Candy, the Ruby method inheritance chain is followed up through Object and then to the mixed-in Kernel module and then this code is run.

nertzy
wrong. It's not defined on Kernel, it's defined on `Object`. `Kernel.instance_methods.include?(:homer) #=> false``Object.instance_methods.include?(:homer) #=> true`
banister
+1  A: 

A simple way to find out what happens

  1. What classes/modules are searched to resolve methods used in Candy objects?

    p Candy.ancestors #=> [Candy, Object, Kernel]

  2. Does Candy have method called homer?

    p Candy.instance_methods(false).grep("homer") #=> []

    p Candy.private_instance_methods(false).grep("homer") #=> []

  3. OK Candy does not have any method called 'homer'.

  4. What's next in the lookup chain (see 1) => "Object"

  5. Does Object have a method called "homer" ? p Object.instance_methods(false).grep("homer") #=> []

    p Object.private_instance_methods(false).grep("homer") #=> ["homer"]

Candy has Object in its lookup chain which in turn has a private instance method "homer" so method resolution succeeds

The def statement always defines the method in the class of whatever self is at the point of definition

  1. What is self just before homer is defined ?

    p self #=> main def homer puts "Hello" end

  2. So what is its type ?

    p self.class #=> Object

Which is why homer ends up on Object