-3

Ruby 2.0 中引入了所谓的改进。我和他们一起玩,现在我完全被哄骗了:

— 声明的主要优点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

是孤立的,不是更糟。

— 改进不支持类方法。呸。当然,它们是通过 hack(记住,一切都是对象):

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故意调用。

— 细化是通过 执行的evalrefine不是关键字。呸。(嗯,“呸!”再次。)

所以,我的问题是:我是否错过了什么或者每个人都认为新引入的功能没有优势?

4

1 回答 1

21

您完全忽略了细化不是全局范围的事实,但这正是引入它们的原因。当然,如果你只是忽略了某事物存在的原因,那么你显然不会看到它的任何价值。

但是,请参阅行动中的隔离。这是修改为使用细化的示例:

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因为你没有使用 Refinements。

在您的情况下,monkeypatch 是全局可用的,因为您只是修改了String类。此功能称为“开放类”,而这正是需要避免的细化。

于 2013-03-05T12:38:50.183 回答