正如问题 Travis Brown 正确的 cmets 中所述,scalac 不会对源文件的路径或名称设置任何此类约束或限制,如果您愿意,您甚至可以在一个文件中指定多个包。
但是,由 scalac 生成的字节码会将字节码类文件放在适当的类加载器所需的必要目录结构中。
这里有一些展示灵活性的例子(我不一定提倡这些风格,只是展示灵活性)。
// in packages1.scala file in local directory
package my {
package states {
sealed trait State
case class CheckingOut(shoppingCartId: Long) extends State
case class ConfirmedOrder(orderId: Long) extends State
case class ItemShipped(orderId: Long, itemId: Long, quantity: Int) extends State
}
}
还有这个……
// in packages2.scala file
package com.foo.bar
sealed trait Scale
case object WebScale extends Scale
case object LolScale extends Scale
case object RoflScale extends Scale
case object WatScale extends Scale
而且这种风格也是可以的:
// in packages3.scala file
package foo {
package awesomeness {
class Main extends App {
println("Bananas are awesome")
}
}
}
package foo {
package lameness {
class Main extends App {
println("Congress is pretty lame, honestly")
}
}
}
还有这个……
package foo
package bar
// now we are in package foo.bar for remainder of file unless another package statement is made
这是生成的源代码和编译后的字节码树:
$ tree
.
├── com
│ └── foo
│ └── bar
│ ├── LolScale$.class
│ ├── LolScale.class
│ ├── RoflScale$.class
│ ├── RoflScale.class
│ ├── Scale.class
│ ├── WatScale$.class
│ ├── WatScale.class
│ ├── WebScale$.class
│ └── WebScale.class
├── foo
│ ├── awesomeness
│ │ ├── Main$delayedInit$body.class
│ │ └── Main.class
│ └── lameness
│ ├── Main$delayedInit$body.class
│ └── Main.class
├── my
│ └── states
│ ├── CheckingOut$.class
│ ├── CheckingOut.class
│ └── State.class
├── packages1.scala
├── packages2.scala
└── packages3.scala
8 directories, 19 files
我不确定 Clojure 是否支持这种灵活性,但 Clojure 约定是使用 Java 构造源代码的约定及其常用的构建工具lein(参见leiningen tutorial here)。
然而,需要注意的一点是,在 Scala 和 Clojure 中,似乎都偏离了 Java 世界中经常使用的 $DOMAIN.$APPLICATION 格式(例如,com.oracle.jdbc...、org.hibernate.session... 等) .在 Scala 中,您会看到包名的 $DOMAIN 部分被完全取出(例如 scalaz...、akka.{actor,io, ...} 等)。
另外值得注意的是您可以从 Scala 中的包中导入的方式:
- 导入
foo.bar 包中的所有公共“事物”:import foo.bar._
- 只导入一个类/特征/等(就像 Java):
import foo.bar.Baz
- 从包中导入一个类/特征/等并在当前范围内重命名:
import foo.bar.{Baz => FooBarBaz}
- 从包中导入一部分东西:
import foo.bar.{Baz, Boo, Bla}
另外值得注意的是 Scala 中的包私有作用域:
package foo.bar
class Baz{
private[bar] def boo[A](a: A)
private[foo] def bla[A](a: A)
}
boo 以上是 foo.bar 包(和子包)私有的,bla 是 foo 及其所有子包的私有。
有关更多详细信息,请阅读 Scala 语言规范和相关链接: