如何在 Ruby 的模块中定义类级宏?

金门斯

在 Ruby 编程语言中,我创建了一个带有类级宏的类,如下所示:

class Timer 
  def self.add_time
    def time
      STDERR.puts Time.now.strftime("%H:%M:%S")      
    end 
  end 
end 

类方法add_time在执行时会生成一个time方法。现在,我可以在另一个类中执行该类级宏,Example如下所示:

class Example < Timer 
  add_time 
end 

当我现在调用timeclass 的实例时Example,该time方法就在那里,正如我所希望的:

ex = Example.new 
ex.time

并打印当前时间:23:18:38

但是现在我想将add_time宏放在一个模块中并且仍然具有相同的整体效果。我试过include这样的:

module Timer 
  def self.add_time
    def time
      STDERR.puts Time.now.strftime("%H:%M:%S")      
    end 
  end 
end 

class Example 
  include Timer
  add_time
end 

ex = Example.new 
ex.time

但后来我收到一个错误,该方法add_time未在类上定义ExampleNameError: undefined local variable or method ‘add_time’ for Example:Class然后我尝试使用这样的extend代替:

class Example 
  extend Timer
  add_time
end

但它给了我一个类似的错误。

所以问题是:如何获得与我的原始示例中相同的效果,其中Timer被定义为类,但使用模块代替?

金门斯

作为@CarySwoveland指出,该方法def self.add_timemodule Timer顺利通过一类夹杂物或延伸忽视。只有模块的实例方法作为类的实例方法(在包含的情况下)或作为类的类方法(在扩展的情况下)添加到类中。

module Timer 
  def add_time # INSTANCE METHOD !
    def time
      STDERR.puts Time.now.strftime("%H:%M:%S")      
    end 
  end 
end 

所以解决方案的第一步是将方法声明def add_time为模块的实例方法。接下来,我们Example使用该模块扩展类,以便将模块的实例方法作为类方法添加到类中Example,然后调用该add_time方法:

class Example 
  extend Timer # EXTEND INSTEAD OF INCLUDE
  add_time
end

然而,这并不能完全按预期工作,因为该time方法现在已作为类方法生成:Example.time打印当前时间01:30:37,但ex的实例Example不理解该方法time

因此,解决方案是将方法生def time成为实例方法而不是类方法。这可以使用 来完成class_eval,这使我们得到以下工作解决方案:

module Timer 
  def add_time # INSTANCE METHOD !
    self.class_eval do # USE class_eval TO DEFINE AN INSTANCE METHOD !
      def time
        STDERR.puts Time.now.strftime("%H:%M:%S")      
      end 
    end 
  end
end 

class Example 
  extend Timer # USE EXTEND TO ADD add_time AS A CLASS METHOD
  add_time
end 

ex = Example.new 
ex.time

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章