4

我们都知道,如果目标类是由模块组成的,则只需调用super一个新模块即可。但是如果它是一个类中的普通方法呢?

class Logger
  def message(msg)
    puts msg
  end
end

比如说,Logger 是一个我无法更改的类(例如它在一个 gem 中)。而且我希望 Logger 在每条消息之前放置一个“================”行。我该如何以美丽的方式做到这一点?遗产?聚合?如何?

4

4 回答 4

3

您可以将原始方法保存为未绑定的方法对象,而不是将其保存在别名中。

然后,您可以使用define_method块。该块将在闭包中捕获未绑定的method_object,允许您在新方法中使用它,而不会污染您的模块/类。

唯一的缺点是,您可能无法以这种方式定义产生或接受块的方法:

module Mod
  unbound_method = instance_method(:original_method)
  define_method :original_method do |*args|
    #do something before
    #call the original method
    unbound_method.bind(self).call(*args)
    #do something after
  end
end
于 2015-03-04T14:11:19.240 回答
2

我会执行子类化(根据@iain 的回答)或在您自己的实例中包含自定义模块:

module LoggerLiner
  def message(*args)
    puts "="*15
    super
  end
end

log = Logger.new(STDOUT)
log.extend(LoggerLiner)
于 2010-12-04T14:48:40.153 回答
2

这可能不是您所说的“美”,但可能最简单的方法是在您的代码中某处:

class Logger
  alias message old_message
  def message(msg)
    puts "================"
    old_message(msg)
  end
end
于 2010-12-04T12:10:50.890 回答
2

您可以从 logger 继承并使用命名空间来使用它:

class LinedLogger < Logger
  def message(*)
    puts "=" * 15
    super
  end
end

当你想使用它时:

class Post
  Logger = LinedLogger
end

只有在命名空间内Post,您才会LinedLogger得到Logger. 这是限制补丁的好方法。但它不会在全球范围内工作。

于 2010-12-04T13:05:23.337 回答