我正在浏览 Facets API 并选择一些方法来包含在我的细化兼容补丁库中。
我在尝试修补内核时遇到了障碍。它是一个模块,而我修补的其他东西是类(字符串、数组等)
这是不能使用我的核心类标准方法进行改进的证据:
module Patch
refine Kernel do
def patched?
true
end
end
end
# TypeError: wrong argument type Module (expected Class)
# from (pry):16:in `refine'
Run Code Online (Sandbox Code Playgroud)
我还尝试将内核模块包装在一个类中,并将对内核的全局引用更改为该类。
class MyKernel
include Kernel
extend Kernel
end
# not sure if Object::Kernel is really the global reference
Object::Kernel = MyKernel
module Patch
refine MyKernel do
def patched?
true
end
end
end
class Test
using Patch
patched?
end
# NoMethodError: undefined method `patched?' for Test:Class
# from (pry):15:in `<class:Test>'
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我可以通过用对象替换内核来成功获得相同的功能:
module Patch
refine Object do
def patched?
true
end
end
end
class Test
using Patch
patched?
end
Run Code Online (Sandbox Code Playgroud)
但我不确定是否可以与其他核心模块(例如 Enumerable)获得这种等价性。
Modules can be refined as of ruby 2.4:
Module#refineaccepts a module as the argument now. [Feature #12534]
The old caveat ("Refinements only modify classes, not modules so the argument must be a class") no longer applies (although it wasn't removed from the documentation until ruby 2.6).
Example:
module ModuleRefinement
refine Enumerable do
def tally(&block)
block ||= ->(value) { value }
counter = Hash.new(0)
each { |value| counter[block[value]] += 1 }
counter
end
end
end
using ModuleRefinement
p 'banana'.chars.tally # => {"b"=>1, "a"=>3, "n"=>2}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
381 次 |
| 最近记录: |