1

私は自分の特性に混ぜようとしている2つのサードパーティライブラリからの特性を持っています。implicit valどちらも。という名前のを定義しますlog

ただし、それらにはさまざまなタイプがあります。1つはSLF4JLoggerで、もう1つはスプレーLoggingContext(実際にはAkkaLoggingAdapterです)です。実際、2番目の特性はSprayからのものであり、それはHttpServerです。(Githubで見つけることができる最新バージョンではありませんが、これはもうありませんval)。

それで、ここにコードがあります(ライブラリ1は独自仕様であるため名前が変更され、Sprayコードは関連する部分だけを表示するために切り取られました):

object LibraryOneShim {
    trait LibraryOne {
        implicit val log: org.slf4j.Logger = ...
    }
}

// https://github.com/spray/spray/blob/a996a5b6bdd830e613583fed86e87bf049fdb8c0/spray-routing/src/main/scala/spray/routing/HttpService.scala
trait HttpService extends Directives {
    val log = LoggingContext.fromActorRefFactory // this is a LoggingContext/LoggingAdapter
}

trait MyTrait extends HttpService with LibraryOne {
    val myRoute = ...
}

class MyActor extends Actor with MyTrait {
    def receive = runRoute(myRoute)
}

これはコンパイルされません。コンパイラは文句を言います:

エラー:タイプjava.lang.ObjectのトレイトHttpServiceのレイジー値ログをspray.util.LoggingContextでオーバーライドします。タイプorg.slf4j.LoggerのトレイトLibraryOne$classの遅延値ログインには「オーバーライド」修飾子が必要ですトレイトDemoServiceはLibraryOneでHttpServiceを拡張します{

これらの2つの特性を一緒に混ぜることができる方法はありますか?

4

1 に答える 1

4

私が知る限り、唯一の方法は作成することですCombinedLogger

class CombinedLogger(l1:Logger, l2:LoggingAdapter) extends Logger with LoggingAdapter {
   // proxy methods to the correct logger
}

両方のロガーがdef次のように使用できると宣言されている場合:

override def log = new CombinedLogger(super[LibraryOne].log, super[HttpService].log)

この場合、val変更されない単一の値であることを Scala コンパイラに伝えるように定義されているため、注意が必要です。そのため、 を呼び出すことはできませんsuper.log。したがって、オーバーライドされた特性のロジックをコピーする必要があります。

この場合のもう 1 つのトリッキーな部分は、CombinedLogger.

于 2013-03-11T23:59:35.800 に答える