如何用 alias_method 打开 class

How to open class with alias_method

我最近一直在阅读 Metaprogrammin Ruby 第 2 版,在第 5 章的末尾,他们提供了一个小测验

Your task is to change Fixnum class so that the answer to 1+1 becomes 3, instead of 2.

教科书上的解法我很不费力的看懂了(他们直接重开Fixnum class)。但我想尽可能多地尝试将方法隔离到一个独立的 Module 。如下所示。

但是下面的 运行 导致在新定义的 + 中无限循环。你能指出这段代码有什么问题吗?提前谢谢你。

module PlusOneMore
  def self.prepended(base)
    base.class_eval{
      alias_method :original_plus, :+
    }
  end
  def +(n)
    original_plus(n).original_plus(1)
  end
end

Fixnum.class_eval do
  prepend PlusOneMore
end

puts 1.+(1)

问题是当执行 prepended 挂钩时,您的覆盖 已经发生 。 IE。当您 运行 alias_method :original_plus, :+ 时,+ 已经指向您的覆盖。

您需要确保在 alias_method 调用之后定义了新方法,或者使用其他方法。

module Foo
  def self.included(klass)
    klass.class_eval do 
      alias_method :original_plus, :+
      define_method(:+) do |n|
        original_plus(n).original_plus(1)
      end
    end
  end
end

Fixnum.include(Foo)

puts 1.+(1)
# => 3

您还可以将 prependsupersucc 一起使用:

module Foo
  def +(n)
    super(n.succ)
  end
end

Fixnum.prepend(Foo)

puts 1.+(1)
# => 3

您也可以使用Ruby refinements来达到类似的效果。

module Foo
  refine Fixnum do 
    alias_method :original_plus, :+
    def +(n)
      (self.original_plus(n)).next
    end
  end
end

using Foo

puts 1 + 1
#=> 3