2013-04-01 101 views
1

下面是一些代碼,我蒸下來,盡我所能:斯卡拉 - 蛋糕圖案+類型類+實現需要構造函數參數

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 
} 

回答

2

簡單的變量初始化順序,這與祖先開始。

首先,在祖先特徵中typeclassInVal被初始化。爲此,調用requireTypeclass。它在Bar中被覆蓋,並且訪問val typeclass,尚未初始化,因此在此時爲空。因此,typeclassInVal初始化爲null,並且您首次使用NPE。

簡單的解決方法可能沒有val,但只是在祖先特徵中的def,或者有一個懶惰的val。

+1

這樣做!絕對需要學習更多關於變量在課堂建設中如何初始化的知識。謝謝! – adelbertc

+1

lazy val是潛在的僵局http://www.youtube.com/watch?feature=player_embedded&v=yLbdw06tKPQ –