Scala-蛋糕图案+;类型类+;需要构造函数参数的实现

Scala-蛋糕图案+;类型类+;需要构造函数参数的实现,scala,typeclass,cake-pattern,Scala,Typeclass,Cake Pattern,下面是我尽可能多地提炼出来的一些代码: trait CakeLayer[A] extends { // typeclass hack to make it play nice with traits implicit def requireTypeclass: MyTypeclass[A] val typeclassInVal = requireTypeclass /* other stuff */ } class FooImpl object FooImpl { im

下面是我尽可能多地提炼出来的一些代码:

trait CakeLayer[A] extends {
  // typeclass hack to make it play nice with traits
  implicit def requireTypeclass: MyTypeclass[A]
  val typeclassInVal = requireTypeclass

  /* other stuff */
}

class FooImpl

object FooImpl {
  implicit object FooImplIsTypeclass extends MyTypeclass[FooImpl]
}

// This works perfectly
class Foo extends CakeLayer[FooImpl] {
  override def requireTypeclass = implicitly
}

// This gives me NullPointerException
// Occurs in a function of my "Bar" that contains an anonymous function
// which uses typeclassInVal. it is the first access to that val
// probably due to the parameter in the typeclass constructor?
class BarImpl(x: Int)

object BarImpl {
  class BarImplIsTypeclass(x: Int) extends MyTypeclass[BarImpl]
}

class Bar(x: Int) extends CakeLayer[BarImpl] {
  val typeclass = new BarImpl.BarImplIsTypeclass(x)
  override def requireTypeclass = typeclass
}

简单的变量初始化顺序,从祖先开始

首先,初始化祖先特征中的
typeclassInVal
。为此,调用
requireTypeclass
。它在
Bar
和access
val-typeclass
中被覆盖,尚未初始化,因此此时为空。因此,
typeclassInVal
被一次性初始化为null,并且您在第一次使用它时会得到一个NPE


简单的解决方法可能不是使用val,而是在祖先特征中使用def,或者使用惰性val。

就是这样!肯定需要学习更多关于如何在类构造期间初始化变量的知识。。谢谢懒惰val是一种潜在的死锁