4

ターゲットクラスがモジュールで構成されている場合はsuper、新しいモジュールを呼び出すだけでよいことは誰もが知っています。しかし、それがクラスの通常のメソッドである場合はどうでしょうか。

class Logger
  def message(msg)
    puts msg
  end
end

たとえば、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

これは「美しさ」が意味するものではないかもしれませんが、おそらく最も簡単な方法は、コードのどこかに次のようにすることです。

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

ロガーから継承し、名前空間を使用して使用できます。

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

そして、あなたがそれを使いたいとき:

class Post
  Logger = LinedLogger
end

名前空間内でのみ、の代わりにPost取得します。これは、パッチを制限するための優れた方法です。ただし、グローバルには機能しません。LinedLoggerLogger

于 2010-12-04T13:05:23.337 に答える
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 に答える