6

给定特征(简化)

trait A {
  val eventStream: EventStream
  val credentialsStorage = // something here
  val userStorage = // something here
  val crypto = // something here
  ...    
  lazy val authSvc = new CoreAuthentication(credentialsStorage, new AuthenticationProviderResolver, userStorage, eventStream, crypto)
}

class T extends A with TraitProvidingEventStream with FlatSpec with [lot of another traits here] {

  val eventStream = systemFromTraitProvidingEventStream.eventStream

  "This" should "work" in {
    println(authSvc) // this is "magic"
    val user = authSvc.doSomethingWithUser(...);
  }
}

如果我删除标记为//this is "magic"的行,那么我将在下一行得到 NullPointerException,因此 authSvc 为空。

那里可能有什么问题?

我无法为此创建干净的小测试用例,通常效果很好

4

1 回答 1

5

这在 ML 上出现过一次:如果在初始化惰性 val 时抛出异常,则 val 为 null;但是您可以尝试再次初始化,它可以神奇地工作。(也就是说,延迟验证的“已初始化”位标志未在第一次尝试初始化失败时设置。)

我认为 ML 上的案例与特征中 vals 的 init 顺序有关,所以也许这就是你的问题。依赖它是出了名的危险,因此建议在特征中使用 defs。请参阅 Luigi 对 DelayedInit 的评论。

于 2012-11-24T18:32:42.117 回答