1

我有来自两个第三方库的特征,我正试图将它们融入我自己的特征中。他们都定义了implicit vals named log

但是,它们有不同的类型——一种是 SLF4J Logger,另一种是 Spray LoggingContext(实际上是 Akka LoggingAdapter)。事实上,第二个特征来自 Spray,它是一个HttpServer. (不是你可以在 Github 上找到的最新版本,它不再有val)。

所以,这里是代码(库一重命名,因为它是专有的,喷雾代码被剪断以显示相关部分):

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)
}

这不会编译。编译器抱怨:

错误:使用 spray.util.LoggingContext 覆盖类型为 java.lang.Object 的 trait HttpService 中的惰性值日志;org.slf4j.Logger 类型的特征 LibraryOne$class 中的惰性值日志需要 `override' 修饰符 trait DemoService extends HttpService with LibraryOne {

有什么办法可以将这两个特征混合在一起吗?

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。所以你需要复制被覆盖特征的逻辑。

在这种情况下,另一个棘手的部分是您需要在CombinedLogger.

于 2013-03-11T23:59:35.800 回答