【问题标题】:How can I dynamically define an alias method for a class method?如何为类方法动态定义别名方法?
【发布时间】:2012-11-04 16:18:21
【问题描述】:

我有一个模块可以调用“计算器”,我想将它包含在“产品”类中。 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

这可行,但名称在类

【问题讨论】:

    标签: ruby


    【解决方案1】:

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

    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
    

    【讨论】:

    • 虽然很好地认为这实际上不是这种情况,因为要别名的方法在模块中进行了扩展,并在尝试别名之前进行了扩展。好主意。
    【解决方案2】:

    所以才知道这样可以解决问题:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多