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

4

Ruby文档中关于refinements的说明如下:

Refinements仅修改类,而不是模块,因此参数必须是类。

为什么会这样?

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

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个回答

2
模块的改进和类的改进一样有用。考虑一下如何改进模块。
module Foobar
  refine Enumerable
    def all_zero?; all? &:zero? end
  end
end

比直接的猴子补丁更礼貌:
module Enumerable
  def all_zero?; all? &:zero? end
end

在优化模块方面存在一个实施问题,现在似乎已经解决了


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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接