Ruby docs on refinements state:
Refinements only modify classes, not modules so the argument must be a class.
为什么是这样?
可以对模块进行猴子修补:
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
我敢肯定这不是一个好主意,但如果你可以限制这种猴子补丁的范围,它可能不会那么糟糕.那你为什么不能呢?
最佳答案 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命名空间而不使用精简.
由于我们没有使用MyModule的实例(MyModule不是类),因此这种方法非常有效.
类是不可能的,因为除了其他原因,类实例可能不限于使用它们的模块的命名空间…因此,对于类实例,应该使用优化.