我最近一直在阅读Metaprogrammin Ruby第二版,在第5章结束时,他们提供了一些小测验
您的任务是更改
Fixnum
课程,以便1+1
的答案变为3
,而不是2
。
我理解教科书中的解决方案没有太大麻烦(他们直接重新开放Fixnum
课程)。但我想尽可能地尝试将方法隔离到独立的Module
。如下所示。
但是在下面运行会导致新定义的+
内的无限lop。你能指出这段代码有什么问题吗?提前谢谢。
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)
答案 0 :(得分: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
您还可以将prepend
与super
和succ
:
module Foo
def +(n)
super(n.succ)
end
end
Fixnum.prepend(Foo)
puts 1.+(1)
# => 3
答案 1 :(得分:2)
您也可以使用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