动态细化
改进有特殊限制。
refine
只能在模块范围内使用,但可以使用 send :refine
进行编程。
using
更受限制。它只能在类/模块定义中调用。但是,它可以接受指向模块的变量,并且可以在循环中调用。
显示这些概念的示例:
module Patch
def patched?; true; end
end
Patch.send(:refine, String) { include Patch }
patch_classes = [Patch]
class Patched
patch_classes.each { |klass| using klass }
"".patched? # => true
end
由于 using
是静态的,如果未首先加载细化文件,则可以发出加载顺序。解决此问题的方法是将修补的类/模块定义包装在 proc 中。例如:
module Patch
refine String do
def patched; true; end
end
end
class Foo
end
# This is a proc since methods can't contain class definitions
create_patched_class = Proc.new do
Foo.class_exec do
class Bar
using Patch
def self.patched?; ''.patched == true; end
end
end
end
create_patched_class.call
Foo::Bar.patched? # => true
调用 proc 会创建补丁类 Foo::Bar
。这可以延迟到所有代码加载完毕之后。