Confusion with a simple Scala packaging example
I've been experiencing confusion over packaging classes in Scala and importing packages. Let me start with a pair of simple source files:
file: 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
}
file: a/b/B.scala
package a.b
class B
usage
Compiling with scalac works without complaint with either of the imports above in A.scala
Trying to load these files in the REPL works differently:
$ 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>
So, I have a some questions:
What is the correct way to do that import in
A.scala
above?The compiler seems to be able to figure out if an import is relative to the package we are in or if it is absolute, without the
_root_
. Is that what I'm seeing?Am I doing this correctly in the REPL? Why does it seem so unhappy with seeing package statements, and why does the
import b._
generate an error?
Thank you
PS I know the directory structure doesn't have to match the packaging. Doing so voluntarily is helping me to be l开发者_StackOverflow中文版ess confused for now.
First off you cannot define packages in the REPL. The reason for this is that your REPL-statements are actually wrapped into object
s. That's why your :load command fails. You would need to compile your source files and add it to the classpath if you want to use packages.
When trying to resolve a symbol to be imported the compiler tries to find it in your actual scope, i.e. when you write
import a._
import b._
this will import everything from package a
and everything from package a.b
. If you are inside package a
then b
is in your scope already and the second import is sufficient.
The compiler also initially imports scala._
so you can also use relative imports like import xml._
to import scala.xml._
.
In addition there is a feature called nested packages which lets you write your B.scala
like
package a
package b
class B { /* .... */ }
which results in everything from package a
being imported in this file.
If the compiler cannot resolve an import to a relative symbol it will look in the default package (_root_
).
To load your class from the console...
scala> :paste -raw io/hacking/yourpackage/YourClass.scala
If your class has a main you can then invoke it with:
scala> io.hacking.yourpackage/YourClass.main(Array())
精彩评论