2017-04-08 63 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

相关问题