我有一个模块可以调用“计算器”,我希望将其包含在“Product”类中。计算器将扩展“Product”,它将类方法复制到Product上。其中一个类方法是“memoize”。这个想法是我可以做这样的事情:
module Calculator
def self.extended(base)
base.memoize :foo_bar
end
end
以记忆方法(特别是类方法)为目的:foo_bar。在memoize中我调用方法“alias_method”,它尝试将类方法别名为另一个名称(此处为:foo_bar)。这失败了。 Memoize看起来像:
module Calculator (the extended module)
def memoize(name)
alias_method "memoized_#{name}", name
end
end
当通过memoize:foo_bar调用它时,alias_method行会发出一条错误,指出Product没有方法“name”..我的理解是因为alias_method会尝试别名实例方法而不是类方法..(我不是我知道为什么但没什么大不了的。)
我可以像这样重新打开本征类
module Calculator
def memoize(name)
class << self
alias_method "memoized_#{name}", name
end
end
end
这样可行,但名称不适用于类的范围&lt;&lt;自我定义。人们已经提到过使用self.class_eval和self.instance_eval,但这两种方法似乎都不起作用..我也喜欢我的蛋糕并且也吃它..我怎么能保持alias_method动态但是在class_methods上使用它?
答案 0 :(得分:3)
所以刚刚得知这将解决问题:
module Calculator
def memoize
define_singleton_method(name, method(name))
end
end
然后当Calculator包含在Product中时,它将根据需要定义单例方法。我仍然不知道为什么alias_method只需要在实例方法上工作..我不知道为什么class_eval或instance_eval没有解决问题..但至少我有一个解决方案..
答案 1 :(得分:3)
如果在include / extend之前将实例方法置为别名,该怎么办?如果您将扩展名放在类名后面,则尚未定义实例方法。
module Foo
def self.extended(base)
base.memoize :flavor
end
def memoize(name)
alias_method "memoized_#{name}", name
end
end
class Bar
def flavor
puts "Orange"
end
extend Foo
end
if __FILE__==$0
b = Bar.new
b.memoized_flavor #=> Orange
end