Why a module's singleton method is not visible in downstream eigenclasses where it gets mixed?
eigenclass, inheritance, mixins, ruby
Solution
First of all, `include` does not include eigenclass methods as you might expect. Consider:
module Foo
class << self
def do_something
puts "Foo's eigenclass method does something"
end
end
end
module Bar
include Foo
end
puts Bar.do_something
# undefined method `do_something' for Bar:Module (NoMethodError)
Note that this is consistent with the behavior of classically defined class methods:
module Foo
def self.do_something
puts "Foo's class method does something"
end
end
module Bar
include Foo
end
puts Bar.do_something
# undefined method `do_something' for Bar:Module (NoMethodError)
A common idiom is to define the class methods in a submodule and then trigger a call to `extend` when the module is included:
module Foo
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def do_something
puts "Foo::ClassMethod's instance method does something"
end
end
end
module Bar
include Foo
end
puts Bar.do_something
# Foo::ClassMethod's instance method does something
The second thing to note is, that you are really including the instance methods of `Automobile` into the eigenclass of `Vehicle`, thus the instance methods of `Automobile` turn into (eigen)class methods of `Vehicle`.
Your `Car` class basically has nothing to do with all this. The only thing to note here is, that class inheritance also makes class methods available, whereas `include` does not. Example:
class Foo
def self.do_something
puts "Foo's class method does something"
end
end
class Bar < Foo
end
puts Bar.do_something
# "Foo's class method does something"
Problem
I understand the regular method lookup path i.e. `class, superclass/module, all the way up to BasicObject`. I thought it was true for singleton version of the chain also but doesn't seem the case when you mixin a module in the meta-chain. I'd appreciate if someone can explain why in the following example `Automobile` module's `banner` method is called instead of its singleton version when I have included this module in Vehicle's eigenclass. ``` module Automobile def banner "I am a regular method of Automobile" end class << self def banner "I am a class method of Automobile" end end end class Vehicle def banner "I am an instance method of Vehicle" end class << self include Automobile def banner puts "I am a class method of Vehicle" super end end end class Car < Vehicle def banner "I am an instance method of Car" end class << self def banner puts "I am a class method of Car" super end end end puts Car.banner # I am a class method of Car # I am a class method of Vehicle # I am a regular method of Automobile ```