As mentioned in the comments to the question Travis Brown is correct, scalac does not place any such constraints or restrictions on the paths or names of files of the source and you can even specify multiple packages in one file if you wish.
However, the bytecode generated by scalac puts the bytecode classes files in the necessary directory structure required by the appropriate classloader.
Here are some examples showing the flexibility (I do not necessarily advocate these styles, just showing the flexibility).
// 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
}
}
And this...
// 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
And this style is possible too:
// 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")
}
}
}
As well as this...
package foo
package bar
// now we are in package foo.bar for remainder of file unless another package statement is made
Here is the resulting source and compiled bytecode tree:
$ 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
I am not sure if Clojure supports such flexibility but Clojure convention is to use the Java convention of structuring source code with it's commonly used build tool lein
(see leiningen tutorial here).
The one thing to note, however, is that in both Scala and Clojure there appears to be a departure from the $DOMAIN.$APPLICATION
format that is often used in the Java world (e.g. com.oracle.jdbc...
, org.hibernate.session...
, etc). In Scala you will see the $DOMAIN part of the package name being taken out completely (e.g. scalaz...
, akka.{actor,io, ...}
, etc.).
Also of note is the way you can import from packages in Scala:
- Import all public "things" in
foo.bar
package:import foo.bar._
- Import just one class/trait/etc (just like Java):
import foo.bar.Baz
- Import one class/trait/etc from package and rename it in current scope:
import foo.bar.{Baz => FooBarBaz}
- Import a subset of things from package:
import foo.bar.{Baz, Boo, Bla}
Also of note is package private scoping in Scala:
package foo.bar
class Baz{
private[bar] def boo[A](a: A)
private[foo] def bla[A](a: A)
}
Above boo
is private to the foo.bar
package (and subpackages) and bla
is private to foo
and all it's subpackages.
For further details read the Scala language specification and related links: