我有这个模块:

module MyMod
  def +(other)
    puts "hello"
  end
end

这将成功覆盖+Fixnum
Fixnum.prepend(MyMod)

123 + :test  # outputs "hello"

假设我需要对+和其他对象重写Fixnum运算符。这将成功覆盖+和其他对象的Fixnum
Fixnum.prepend(MyMod)
Object.include(MyMod)

123 + :test  # outputs "hello"

但如果我更改prependinclude的顺序,则覆盖无效:
Object.include(MyMod)
Fixnum.prepend(MyMod)

123 + :test  # error: -:10:in `+': :test can't be coerced into Fixnum (TypeError)

为什么includeprepend的顺序在这里有这种效果?

最佳答案

参见Module#prepend_features的文档:
当这个模块在另一个模块中前置时,ruby调用这个模块中的prepend_特性,将接收模块传入mod。ruby的默认实现是将这个模块的常量、方法和模块变量覆盖到mod,如果这个模块还没有被添加到mod或它的祖先中。另请参见“准备”模块。
因此,prepend只在其参数尚未添加到接收器或其祖先之一时才执行任何操作。因为ObjectFixnum的祖先,所以当在Fixnum.prepend(MyMod)之后调用时,Object.include(MyMod)不会执行任何操作。

10-05 20:31