4

关于改进的Ruby 文档状态

改进只修改类,而不是模块,所以参数必须是一个类。

为什么是这样?

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

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

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

4

2 回答 2

2

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

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

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

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

精炼模块存在实施问题,现在似乎已解决

于 2016-11-11T19:25:56.670 回答
0

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

这些相同的继承问题不适用于模块,因为模块可以使用 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( MyModuleis NOT a class) 的实例,因此这种方法非常有效。

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

于 2015-10-12T05:40:50.983 回答