合并数组时继承自定义方法

Inherit custom methods when merging arrays

我在数组实例上定义了一些自定义方法,例如:

a = [1, 2]
b = [3, 4]

a.define_singleton_method(:foo) do
  "foo"
end

a.foo
# => "foo"

是否可以传递/继承/保留这个自定义方法,当a数组被添加到另一个数组(或任何其他数组操作如uniq,交集...) 例如:

(a + b).foo
# undefined method `foo' for [1, 2, 3, 4]:Array (NoMethodError)

这是有道理的,因为创建了一个新数组。但是我想知道是否有一种方法可以在新创建的数组上保留 a 数组上的自定义方法。 当然,我可以通过调用 define_singleton_method 的相同步骤传递每个数组,但这会变得非常复杂,您很容易忘记一个数组。

可以写一个ArrayViralArray子类,它覆盖每个Array方法来产生一个新的数组,其中包括你的额外方法.

class ViralArray < Array
  [:+, :*, :-].each { |method|
    define_method(method) do |*args|
      new_array = super(*args)
      new_array.define_singleton_method(:foo) do
        "foo"
      end
      new_array
    end
  }
end

my = ViralArray[1,2,3]
b = my + [4,5,6]
p b.foo    # "foo"
p b.class  # Array

这显然很乏味并且容易损坏。

但是像这样的病毒式方法使得代码很难理解。你永远不知道哪些数组有#foo,哪些没有。

相反,refine Array。细化就像猴子修补,但范围有限。

定义 Array 的细化,添加 #foo.

module FooArray
  refine Array do
    def foo
      "foo: #{object_id}"
    end
  end
end

并在需要使用 foo 方法的数组的代码中使用它。

using FooArray

a = [1,2,3]
puts a.foo

所有其他代码将不受影响。