如何用 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
您还可以将 prepend
与 super
和 succ
一起使用:
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
我最近一直在阅读 Metaprogrammin Ruby 第 2 版,在第 5 章的末尾,他们提供了一个小测验
Your task is to change
Fixnum
class so that the answer to1+1
becomes3
, instead of2
.
教科书上的解法我很不费力的看懂了(他们直接重开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
您还可以将 prepend
与 super
和 succ
一起使用:
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