顶级实例方法

时间:2015-04-16 09:38:52

标签: ruby

我有这段代码:

module M
  def m
    "hello"
  end
end

include M

m # => hello
M.m # => hello

M添加到顶层,我可以致电m。为什么我可以致电M.m

3 个答案:

答案 0 :(得分:4)

在顶层调用include M包括Object中的模块:

module M
  def m
    "hello"
  end
end

include M

Object.included_modules #=> [M, Kernel]

您可以通过以下方式实现相同目标:

class Object
  include M
end

因为Ruby中的所有内容都是对象,所以您可以将m发送到每个对象 1 ,包括实例,类和模块(如M):

123.m        #=> "hello"
'foo'.m      #=> "hello"
String.m     #=> "hello"
Object.m     #=> "hello"
Enumerable.m #=> "hello"
M.m          #=> "hello"

1 is_a? Object

意义上的对象

答案 1 :(得分:1)

"默认定义" (即,definclude d mixins定义的方法结束的模块)在顶层是Object

这意味着M被包含在Object中,即M成为Object的超类,插入Kernel下方。由于M是模块的实例,而ModuleObject的子类,而Object现在是M的子类,因此可以调用{ {1}}。

M.m的祖先链是:

Module

ergo,[Module, Object, M, Kernel, BasicObject] 位于M的方法查找路径中,因此M找到M.m中定义的方法。

答案 2 :(得分:0)

更奇怪的例子:

▶ module M ; end
▶ def m ; puts '¡Hola!' ; end
#⇒ :m
▶ M.m
#⇒ ¡Hola!

所以,让我们深入研究对象继承。执行上下文是mainmain显然是Object的“特殊”实例,传播其上定义的所有方法,随处可见。由于Module实例(M)实际上是Object的实例,因此它会突然响应每个Object方法。但我们只使用Object方法扩展了m

注意:顶级module M ; def m ; end ; end; include Mdef m ; end几乎完全相同:都使用Object方法扩展m(后者使此方法{{1}但是在private上。)

希望它有所帮助。