Question

In the "rubymonk" and some other ruby resources, it is mentioned that when you define a singleton method on an object, under the hood, Ruby is adding this new method to the object's metaclass. right? and also there is a trick to access the metaclass and it is it:

class Object
  def metaclass
    class << self
      self
    end
  end
end

foo = "I'm a string object"

def foo.shout
  puts self.upcase
end

foo.shout

p foo.metaclass.class
p foo.class.instance_methods.include? :shout
p foo.metaclass.instance_methods.include? :shout

and as we all expect, the result is:

I'M A STRING OBJECT
Class
false
true

and everything is ok. but what if we change the metaclass method to return Hash instead of self?

  class Object
      def metaclass
        class << self
          Hash
        end
      end
    end

and then we check these things:

p foo.class.instance_methods.include? :shout
p foo.metaclass.instance_methods.include? :shout
p String.instance_methods.include? :shout
p Object.instance_methods.include? :shout
p Hash.instance_methods.include? :shout

and yeah, all of them are false:

false
false
false
false
false

the question is, what does shout method belong to now? it is not the metaclass. so what is it?!

Was it helpful?

Solution

Still the metaclass, you've just removed your ability to access it directly...

foo.instance_eval { class << self; self; end.instance_methods.include?(:shout) }
  => true

OTHER TIPS

shout still belongs to the metaclass, and you haven't even lost your ability to access the metaclass (as the other answers suggest). You've just created a useless method on Object called metaclass. That doesn't stop you from doing the following:

 (class << any_object_here; self; end)

Note that the class << ... syntax is core Ruby syntax and cannot be "changed" just by redefining a method.

The shout method still belongs to foo's metaclass, you just do not have access to it as you chose to always return Hash from your method. The method definition of foo.shout is not affected by the semantics of your metaclass method.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top