为什么Ruby改进只修改类而不是模块?

时间:2015-10-12 00:01:27

标签: ruby refinements

Ruby docs on refinements state

  

优化只修改类,而不修改模块,因此参数必须是类。

为什么会这样?

可以对模块进行猴子修补:

module MyModule
  def my_method
    "hello"
  end
end

include MyModule
puts my_method # => hello

module MyModule
  def my_method
    "goodbye"
  end
end

puts my_method # => goodbye

我确定这不是一个好主意,但如果你可以限制这种猴子补丁的范围,那可能不会那么糟糕。那你为什么不能?

2 个答案:

答案 0 :(得分:2)

模块的细化与类的细化一样有用。考虑如何

module Foobar
  refine Enumerable
    def all_zero?; all? &:zero? end
  end
end

比直接猴子补丁更有礼貌:

module Enumerable
  def all_zero?; all? &:zero? end
end

implementation issue个精炼模块,seems to be solved by now

答案 1 :(得分:0)

Ruby中的refine旨在处理猴子修补和继承问题,其目的是将猴子修补限制为特定命名空间中的类实例。

这些相同的继承问题不会以相同的方式应用于模块,因为模块可以使用mixin扩展或包含在其他模块中(而不是类)。

这将允许通过创建一个新模块来限制猴子修补程序,该模块在其自己的命名空间内扩展和覆盖原始模块。

如果要使用您的示例:

module MyModule
  def my_method
    "hello"
  end
end

include MyModule

puts my_method
# => hello

module MyOtherModule
  extend MyModule

  puts my_method # will print: hello

  def my_method
    "goodbye"
  end
  extend self

  puts my_method # will print: goodbye
end
# => hello
# => goodbye

puts my_method
# => hello

正如您所看到的,我们设法将'monkey-patch'限制在MyOtherModule命名空间而不使用refine

由于我们没有使用MyModule的实例(MyModule不是一个类),这种方法非常有效。

类不可能这样,因为除了其他原因,类实例可能不限于使用它们的模块的命名空间...因此,对于类实例,应使用refine