2017-04-08 61 views
7

請考慮下面的代碼:從不能用作構造函數參數的默認值同伴進口類

object Main extends App { 
    object Project { 
    case class Config(rules: Seq[String] = Seq.empty) 
    } 

    import Project._ 

    //case class Project(root: String, config: Config) // compiles fine 

    //case class Project(root: String, config: Project.Config = Project.Config()) // compiles fine 

    case class Project(root: String, config: Config = Config()) // error: not found: type Config 

} 

爲什麼最後一個版本不編譯(同與Config = Config.apply())?

+0

它看起來像我的錯誤。 –

+0

它可能與'case class's在他們的伴侶對象中添加一些代碼的事實有關,所以他們在正確定義之前訪問它時遇到了麻煩。然而,你可以在Project的構造函數中訪問(隱式定義的)'Project.apply',所以對我來說真的很奇怪。 –

+0

當我將伴隨對象放在案例類後面時,它就起作用。 – Suma

回答

2

這不是我清楚,如果這是一個錯誤或沒有,但在這裏就是爲什麼它會產生一個錯誤:

考慮這一點,它的工作原理:

import Project._ 

object Project { 
    case class Config() 
} 

case class Project(config: Config = Config()) 

當您添加默認參數編譯器會生成一個計算值的方法。當該值爲構造函數默認值時,該方法將添加到類的伴隨對象中。所以編譯器會生成這個方法:

def <init>$default$1: Project.Config = Config() 

這會被添加到您的Project對象中。

斯卡拉類型檢查器生成Contexts的對象樹。每個上下文都有對其外部範圍的上下文的引用。所以生成的方法獲取上下文,生成的方法的外部作用域是Project隨播對象。

當類型檢查器試圖解決Config()它遍歷所有封閉的上下文並找不到Config(我不知道爲什麼,這可能是一個錯誤)。

一旦耗盡了上下文,它將解析導入Project._的導入!類型檢查器很高興,因爲它現在可以遍歷導入並找到apply方法。

現在,當你移動下面Project進口:

object Project { 
    case class Config() 
} 

import Project._ 

case class Project(config: Config = Config()) 

在這種情況下所產生的方法可用進口不具有Project._進口(這也可能是一個bug),我假設,因爲它低於生成的方法所在的對象定義。類型檢查器然後會拋出錯誤,因爲它找不到Config

這似乎是發生的事情是,當類型檢查的解決Config()它需要Project同伴對象上方的進口,因爲它需要處理的進口能夠解決它,除非進口高於Project即導入範圍內不是

對於那些誰希望進一步調試看看Contexts.lookupSymbol這哪裏是查找正在發生

+0

在伴侶提供一個很好的(即使有點奇怪)解決方法之前放置導入。 – Suma

相關問題