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())?

4

1 回答 1

2

我不清楚这是否是一个错误,但这就是它产生错误的原因:

考虑一下,它有效:

import Project._

object Project {
  case class Config()
}

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

当您添加默认参数时,编译器会生成一个方法来计算该值。当该值是构造函数默认值时,该方法将添加到类的伴随对象中。所以编译器会生成这个方法:

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

这将被添加到您的Project对象中。

Scala 类型检查器生成一个Contexts. 每个上下文都有对其外部范围的上下文的引用。所以生成的方法获得了一个上下文,并且生成的方法的外部范围是Project伴随对象。

当类型检查器尝试解析Config()时,它会遍历所有封闭上下文并且找不到Config(我不确定为什么,这可能是一个错误)。

一旦它用尽了上下文,它就会解析具有 import 的导入Project._!类型检查器很高兴,因为它现在可以遍历导入并找到应用方法。

现在,当您将导入移至下方时Project

object Project {
  case class Config()
}

import Project._

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

在这种情况下,生成方法可用的导入没有Project._导入(这也可能是一个错误),我假设因为它位于生成方法所在的对象定义之下。然后类型检查器会抛出一个错误,因为它找不到Config.

似乎正在发生的事情是,当类型检查器解析时Config(),它需要在伴随对象上方导入,Project因为它需要处理导入才能解析它,除非导入高于Project该导入不在范围内。

对于那些希望进一步调试的人,请查看Contexts.lookupSymbol查找发生的位置

于 2017-04-08T17:25:36.827 回答