In Ruby, the method puts
is a singleton method of the Kernel
module.
Normally, when a module is include
d or extend
ed by another module, the module (but not its singleton class) is added to the inheritance tree. That effectively makes the instance methods of the module available to either the module or its singleton class (for include
and extend
, respectively)... but the singleton methods of a mixed-in module remain inaccessible, because the singleton class of a module isn't ever added to the inheritance tree.
So why can I use puts
(and other Kernel singleton methods)?
Kernel.singleton_methods(false)
# => [:caller_locations, :local_variables, :require, :require_relative, :autoload, :sprintf, :format, :Integer, :Float, :String, :Array, :Hash, :test, :warn, :autoload?, :fork, :binding, :exit, :raise, :fail, :global_variables, :__method__, :__callee__, :__dir__, :URI, :eval, :iterator?, :block_given?, :catch, :throw, :loop, :gets, :sleep, :proc, :lambda, :trace_var, :untrace_var, :at_exit, :load, :Rational, :select, :Complex, :syscall, :open, :printf, :print, :putc, :puts, :readline, :readlines, :`, :p, :system, :spawn, :exec, :exit!, :abort, :set_trace_func, :rand, :srand, :trap, :caller]
Note that puts
does not seem to be an instance method on Kernel
:
Kernel.instance_methods.grep(/puts/)
# []
Although Object
does include Kernel
Object.included_modules
# [Kernel]
as far as I can tell, Kernel
's singleton class (#<Class:Kernel>
) doesn't show up in the ancestors of any object. is_a?
appears to agree with this:
Object.is_a? Class.singleton_class # false
Object.is_a? Kernel.singleton_class # false
Object.singleton_class.is_a? Class.singleton_class # true
Object.singleton_class.is_a? Kernel.singleton_class # false
Yet, for some reason, they show up as private methods for every object.
Object.puts "asdf"
# NoMethodError (private method `puts' called for Object:Class)
How does the method lookup find these methods at all if #<Class:Kernel>
doesn't show up in the ancestor chain?
Related:
- Ruby method lookup path for an object
- Class, Module, their eigenclasses, and method lookup
- Note: this is different from what I'm asking, because this is class inheritance, so
#<Class:Class>
inherits from#<Class:Module>
- Note: this is different from what I'm asking, because this is class inheritance, so
- Why a module's singleton method is not visible in downstream eigenclasses where it gets mixed?
Object
includes theKernel
module, butputs
et al. are not methods onKernel
-- they are methods onKernel
's singleton class, and thus should not be accessible toObject
– Breland