如何使用alias_method打开类

Oka*_*uta 1 ruby metaprogramming

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

你的任务是更改Fixnum类,以便答案1+1变为3,而不是2.

我理解教科书中的解决方案没有太多麻烦(他们Fixnum直接重新开课).但我想尽可能地尝试将独立方法分离到一个独立的方法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)
Run Code Online (Sandbox Code Playgroud)

Jes*_*per 5

问题是在执行挂钩时已经发生了覆盖prepended.即,当你跑步时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
Run Code Online (Sandbox Code Playgroud)

您还可以使用prependsupersucc:

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

Fixnum.prepend(Foo)

puts 1.+(1)
# => 3
Run Code Online (Sandbox Code Playgroud)

  • 这个.'prepend`的*整点*,*为什么它首先被引入的原因是*摆脱*那个神圣的'alias_method`舞蹈. (2认同)