与简单的Scala包装示例混淆

din*_*ino 2 scala package scala-2.8

我一直在使用Scala中的包装类和导入包时遇到困惑.让我从一对简单的源文件开始:

档案:a/A.scala

package a

// Which of these imports should be used? They both seem to work.
//import a.b._
import b._

class A {
   val fieldB = new B
}
Run Code Online (Sandbox Code Playgroud)

档案:a/b/B.scala

package a.b

class B
Run Code Online (Sandbox Code Playgroud)

用法

使用scalac进行编译时无需投诉A.scala中的任何导入

尝试在REPL中加载这些文件的方式不同:

$ scala
Welcome to Scala version 2.8.0.r0-b20100714201327 (Java HotSpot(TM) Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :l a/b/B.scala
Loading a/b/B.scala...
<console>:1: error: illegal start of definition
       package a.b
       ^
defined class B

scala> :l a/A.scala
Loading a/A.scala...
<console>:1: error: illegal start of definition
       package a
       ^
<console>:5: error: not found: value b
       import b._
              ^
defined class A

scala>
Run Code Online (Sandbox Code Playgroud)

所以,我有一些问题:

  • A.scala上面进行导入的正确方法是什么?

  • 编译器似乎能够确定导入是否与我们所在的包相关,或者它是否是绝对的,没有_root_.这就是我所看到的吗?

  • 我是否在REPL中正确地这样做了?为什么它看起来如此不满意看到包语句,为什么会import b._产生错误?

谢谢

PS我知道目录结构不必与包装相匹配.自愿这样做可以帮助我减少现在的困惑.

Mor*_*itz 6

首先,您无法在REPL中定义包.原因是你的REPL语句实际上包含在objects中.这就是你的:load命令失败的原因.如果要使用包,则需要编译源文件并将其添加到类路径中.

在尝试解析要导入的符号时,编译器会尝试在您的实际范围内找到它,即在您编写时

import a._
import b._
Run Code Online (Sandbox Code Playgroud)

这将从中导入所有package a内容package a.b.如果你在里面package a那么b已经在你的范围内,第二次导入就足够了.编译器最初也会导入,scala._因此您也可以使用相对导入import xml._来导入scala.xml._.

此外,还有一个称为嵌套包的功能,可以让您编写B.scala类似的功能

package a
package b
class B { /* .... */ }
Run Code Online (Sandbox Code Playgroud)

这导致从此package a文件导入的所有内容.

如果编译器无法解析导入到相对符号,它将查找默认包(_root_).