在 Ruby 中,该方法puts
是Kernel
模块的单例方法。
通常,当一个模块被另一个模块include
d 或extend
ed 时,该模块(但不是它的单例类)被添加到继承树中。这有效地使模块的实例方法可用于模块或其单例类(分别为include
和extend
)......但是混合模块的单例方法仍然不可访问,因为模块的单例类不是曾经添加到继承树中。
那么为什么我可以使用puts
(和其他内核单例方法)?
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]
请注意,这puts
似乎不是实例方法Kernel
:
Kernel.instance_methods.grep(/puts/)
# []
虽然Object
包括Kernel
Object.included_modules
# [Kernel]
据我所知,Kernel
的单例类 ( #<Class:Kernel>
) 不会出现在任何对象的祖先中。is_a?
似乎同意这一点:
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
然而,出于某种原因,它们显示为每个对象的私有方法。
Object.puts "asdf"
# NoMethodError (private method `puts' called for Object:Class)
如果#<Class:Kernel>
没有出现在祖先链中,方法查找如何找到这些方法?
有关的:
- 对象的 Ruby 方法查找路径
- 类、模块、它们的特征类和方法查找
- 注意:这与我要求的不同,因为这是类继承,所以
#<Class:Class>
继承自#<Class:Module>
- 注意:这与我要求的不同,因为这是类继承,所以
- 为什么模块的单例方法在混合的下游特征类中不可见?