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
和accessval-typeclass
中被覆盖,尚未初始化,因此此时为空。因此,typeclassInVal
被一次性初始化为null,并且您在第一次使用它时会得到一个NPE
简单的解决方法可能不是使用val,而是在祖先特征中使用def,或者使用惰性val。就是这样!肯定需要学习更多关于如何在类构造期间初始化变量的知识。。谢谢懒惰val是一种潜在的死锁