Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby Kernel module methods used as Object class methods

Say I want to patch the Kernel module with one method I just came up with:

module Kernel
  def say_hello
    puts "hello world"
  end
end

I can now certainly do this:

Object.new.say_hello # => hello world

but I can also do the following which I normally shouldn't be able to do:

Object.say_hello # => hello world

Since Object includes Kernel it takes its instance methods and thus all Object instances should respond to say_hello. So far so good.

However Object.say_hello seems to be a class method which could only be justified if we had done something similar to this:

class << Object
  def say_hello
    puts "hello world"
  end  
end

Storing say_hello in Object's singleton class would allow us to use it as a class method but instead Kernel in just included in Object which shouldn't allow this behavior. But it does. Does anybody have a clue why?

Thanks

like image 438
stratis Avatar asked Sep 10 '26 04:09

stratis


1 Answers

Kernel is just included in Object [...]

That is correct.

[...] which shouldn't allow this behavior.

You overlook that classes are objects, too.


Let's see where the say_hello method comes from if obj is an instance of Object:

obj = Object.new

obj.method(:say_hello)
#=> #<Method: Object(Kernel)#say_hello>

Just as expected. obj is an instance of Object and Object includes Kernel:

obj.class.include? Kernel
#=> true

obj.class.ancestors
#=> [Object, Kernel, BasicObject]

Now let's see what happens if obj is the class Object:

obj = Object

obj.method(:say_hello)
#=> #<Method: Class(Kernel)#say_hello>

This time obj is an instance of Class and Class also includes Kernel:

obj.class.include? Kernel
#=> true

obj.class.ancestors
#=> [Class, Module, Object, Kernel, BasicObject]

Ruby's documentation notes that class methods are in fact just instance methods defined on the class object: (emphasis added)

class C
  def self.my_method
    # ...
  end
end

However, this is simply a special case of a greater syntactical power in Ruby, the ability to add methods to any object. Classes are objects, so adding class methods is simply adding methods to the Class object.

like image 153
Stefan Avatar answered Sep 13 '26 05:09

Stefan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!