Search code examples
rubyruby-2.5

class method `self.` within class methods block `class << self` in Ruby


context: I'm currently working with the parser gem and trying to handle all cases of what is a public method.

I've written this next code, hoping it will fail on runtime. But it doesn't.

class Foo
  class << self
    def self.met
      puts "I'm just a troll"
    end

    class << self
      def mut
        puts "Try and find me"
      end
    end
  end
end

So I'm wondering where is met callable (Foo.met would raise a NoMethodError)? And is this a useful Ruby pattern or just something I should not do, neither care about?


Solution

  • Each object in Ruby has its own singleton class. This is where all the methods of instances are defined.

    Consider the following example.

    class C; end
    c1, c2 = C.new, C.new
    c1.extend(Module.new { def m1; 42; end })
    
    c1.m1
    #⇒ 42
    c2.m1
    #⇒ NoMethodError: undefined method `m1' for #<C:0x000055cb062e6888>
    
    c1.singleton_class.instance_methods.grep /m1/
    #⇒ [:m1]
    c2.singleton_class.instance_methods.grep /m1/
    #⇒ []
    

    Singleton class is needed to make it possible to extend objects etc.

    In Ruby, everything is object. Classes are indeed objects as well. That’s why each class has its own singleton class. And each singleton class has its singleton class.

    c1.singleton_class.singleton_class.singleton_class.singleton_class
    #⇒ #<Class:#<Class:#<Class:#<Class:#<C:0x000055cb0459c700>>>>>
    

    Methods defined on foo are stored in the singleton class of foo. Methods defined on foo’s singleton class are stored in the singleton class of the singleton class of foo. And so forth.

    It’s not quite practical, but it’s still possible due to how Ruby treats everything as Object.