6

我有一个模块可以调用“计算器”,我想将其包含在“产品”类中。Calculator 将扩展“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 has no method "name".. 我的理解是这是因为 alias_method 将尝试为实例方法而不是类方法.. (我不知道为什么但没关系,没什么大不了的)..

我可以像这样重新打开特征类

module Calculator
  def memoize(name)
    class << self
      alias_method "memoized_#{name}", name
    end
   end
end

这会起作用,但名称在类 << 自我定义的范围内不可用。人们提到使用 self.class_eval 和 self.instance_eval 但这些似乎都不起作用..我也想要我的蛋糕并吃掉它..我怎样才能保持 alias_method 动态但在 class_methods 上使用它?

4

2 回答 2

3

所以刚刚了解到这会成功:

module Calculator
  def memoize
    define_singleton_method(name, method(name))
  end
end

然后,当 Calculator 包含在 Product 中时,它将根据需要定义单例方法。我仍然不知道为什么 alias_method 只需要在实例方法上工作.. 我不知道为什么 class_eval 或 instance_eval 没有解决问题.. 但至少我有一个解决方案..

于 2012-11-15T23:48:45.440 回答
3

如果在包含/扩展之前将实例方法设置为别名怎么办?如果您将扩展名放在类名之后,则尚未定义实例方法。

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
于 2012-11-16T06:05:25.957 回答