Ruby 2.0中引入了所谓的refinements。我和他们一起玩,现在我完全被哄骗了:
- refine
的主要宣称优势是它们不是全局范围的。呸。
module MyModule
class ::String
def my_locally_needed_func
# do smth
end
end
end
# here I need it
require 'mymodule'
"".my_locally_needed_func
孤立并不差。
- 优化不支持类方法。呸。当然,他们是通过黑客攻击(记住,一切都是对象):
module VoidRefinements
refine String do
def self.singleton_method_for_string_class
puts "inside singleton_method_for_string_class"
end
end
end
module VoidRefinementsOK
refine Class do
def singleton_method_for_string_class
err_msg = "NoMethodError: undefined method ‘#{__method__}’ for ‘#{self}:#{self.class}’"
raise NoMethodError.new(err_msg) unless String == self
puts "inside proper singleton_method_for_string_class"
end
end
end
using VoidRefinements
String.singleton_method_for_string_class rescue puts $!
using VoidRefinementsOK
String.singleton_method_for_string_class rescue puts $!
# undefined method `singleton_method_for_string_class' for String:Class
# inside proper singleton_method_for_string_class
后者甚至没有导致性能损失,因为没有人会故意拨打Fixnum.substr
。
- 通过eval
执行优化。 refine
不是关键字。呸。 (好吧,“呸!”再次。)
所以,我的问题是:我错过了什么,或者每个人都认为新推出的功能没有优势?
答案 0 :(得分:21)
你完全不认为Refinements不是全局范围的,但这就是它们被引入的原因。当然,如果你只是忽略某事物存在的原因,那么你显然不会看到任何价值。
但是,看看行动中的孤立。以下是修改后使用优化的示例:
module MyModule
refine String do
def my_locally_needed_func
# do smth
end
end
end
module MyOtherModule
# The monkeypatch is invisible:
"".my_locally_needed_func
# NoMethodError: undefined method `my_locally_needed_func' for "":String
# I first have to use the Refinement:
using MyModule
"".my_locally_needed_func
end
# The monkeypatch is scoped. Even though we were able to use
# it in MyOtherModule, we still cannot use it at the top-level:
"".my_locally_needed_func
# NoMethodError: undefined method `my_locally_needed_func' for "":String
# We have to call `using` again, for the top-level:
using MyModule
"".my_locally_needed_func
以下是您的示例进行比较:
module MyModule
class ::String
def my_locally_needed_func
# do smth
end
end
end
# here I need it
"".my_locally_needed_func
注意:我删除了对using
的调用,因为您还没有使用优化,所以没有任何意义。
在您的情况下,monkeypatch是全局可用的,因为您只是修改了String
类。这个功能被称为“开放类”,正是Refinements要避免的。