Published 2013-12-29.
Last modified 2016-02-05.
Time to read: 5 minutes.
This lecture discusses Scala’s imports and package concepts.
Like Java, source files can be grouped into packages.
Unlike Java, the directory structure is decoupled from the Scala packages.
Furthermore, you can scope a package, so that only a portion of a source file resides within a package.
Here is a sample file, called TemporalSpatial.scala
.
Two classes are defined: com.micronautics.Temporal
and com.micronautics.alternate.Spatial
.
These classes are all provided in the courseNotes
SBT project.
package com.micronautics
class Temporal
package alternate { class Spatial { println(s"Spatial’s constructor says that doubling 21 gives ${doubler(21)}") } }
Just to make a point, the file above is in the a/b/c
source directory.
The point I am making is that the organization on disk is quite unrelated to the package
statements.
You can put all your classes in the same directory, even if they declare different packages, or you can put them in completely random directories.
I do not recommend this, but it is possible.
The Scala compiler only looks at the package
statements to determine the package structure of your code.

Package Objects and package.scala
Scala 2 had package object
s, which can contain package-level definitions.
Scala 3 dropped package object
s,
so if you are only interested in Scala 3 you can skip this section.
package object bar { ... }
... is just syntactic sugar for:
package bar { object `package` { ... } }
Usually package objects just define methods, properties and implicits, as well as package-level documentation in package object
s.
Looking ahead to the lectures on implicits of the
Intermediate Scala course
(Implicit Values,
Implicit Conversions,
and Implicit Classes),
you could mix in traits that define implicits into the package object to make the implicits available any time the package is imported.
We’ll see examples of how that works in the Intermediate Scala course.
Package-level documentation should provide an overview of the major classes, with some basic examples of how to use the classes in that package.
By convention, package objects are frequently defined in a file called package.scala
,
however this is not a requirement.
You can place package objects in any file with a .scala
filetype.
Here is an example of a package object which I have placed in package.scala
in the courseNotes
project.
Notice that the doubler
method is defined within a package object
for the package com.
.
You can invoke doubler
from anywhere in the com.
package without qualification because
package
object
s are automatically imported into the package of the same name.
This is actually done in the constructor for class Spatial
,
which evaluates doubler(21)
and prints the result.
Notice that I referenced classes in the Scaladoc using square-bracket notation.
/** Provides classes for whatever it is that this package does. * Also provides implicits related to this class. * * ==Overview== * The main class to use is [[com.micronautics.Whatever]]. * {{{ * scala> doubler(3) * res0: Int = 6 * }}} */ package object alternate { def doubler(x: Int): Int = x * 2 }
Here is an entry point for a console application that exercises the classes above,
rather like how Java’s static main
method works:
object PackageDemo extends App { val ceeABC = new com.micronautics.Temporal val ceeXYZ = new com.micronautics.alternate.Spatial }
We can run the above Scala 2 code from the command line as follows:
$ sbt "run-main PackageDemo" [info] Loading global plugins from /home/mslinn/.sbt/0.13/plugins [info] Loading project definition from /var/work/course_scala_intro_code/courseNotes/project [info] Updating {file:/var/work/course_scala_intro_code/courseNotes/project/}coursenotes-build... [info] Resolving org.fusesource.jansi#jansi;1.4 ... [info] Done updating. [info] Set current project to scalaIntroCourse (in build file:/var/work/course_scala_intro_code/courseNotes/) Spatial’s constructor says that doubling 21 gives 42 [success] Total time: 7 s, completed Dec 17, 2013 10:17:19 PM
Packages in the REPL
Prior to Scala 2.11, package
statements could not be entered in the REPL.
Since then, you still cannot use a package
statement in the REPL without doing the proper dance.
scala> package x <console>:1: error: illegal start of definition package x
scala> package { val x = 0 } <console>:1: error: illegal start of definition package { val x = 0 }
scala> package object { val x = 0 } <console>:1: error: illegal start of definition package object { val x = 0 }
Scala 2.11 introduced a new dance partner, :paste -raw
, which allows defining packages in the REPL.
Without this, you cannot access artifacts from the REPL in other packages that have restricted visibility.
We will learn more about access modifiers and visibility in the
Deceptively Familiar: Access Modifiers lecture.
scala> :paste -raw // Entering paste mode (ctrl-D to finish)
package foo class Bar ^D // Exiting paste mode, now interpreting.
Now you can create instances:
scala> new foo.Bar res2: foo.Bar = foo.Bar@10289886
scala> import foo.Bar import foo.Bar
scala> new Bar res3: foo.Bar = foo.Bar@2d1dee39
You can define classes, traits and objects.
scala> :paste -raw // Entering paste mode (ctrl-D to finish)
package y object z { val a = 0 } ^D // Exiting paste mode, now interpreting.
scala> y.z res5: y.z.type = y.z$@56193c7d
:paste -raw Limitations
You cannot define top-level variables using:paste -raw
:
scala> :paste -raw // Entering paste mode (ctrl-D to finish)
package x val a = 0 ^D // Exiting paste mode, now interpreting.
<pastie>:2: error: expected class or object definition val a = 0 ^ There were compilation errors!
It does not matter if you try to define a top-level variable or method after a package
statement or
within a scoped package
, like this:
scala> :paste -raw // Entering paste mode (ctrl-D to finish)
package x { val x = 0 } ^D // Exiting paste mode, now interpreting.
<pastie>:2: error: expected class or object definition val x = 0 ^ There were compilation errors!
Handy Trick for Scala 2 Only
Because Scala 3 removed package object
s, this trick only applies to Scala 2.
You can escape Scala keywords by enclosing them in `backticks`.
This allows us to nest an object named package
inside another package –
effectively defining a package object for the current package scope.
In this example, I define a variable called theNextAnswer
in the package object for package a.b.c
.
package a.b.c
/** Here is some package-level documentation */ object `package` { val theNextAnswer = 43 }
Code Review Fail
You can escape any Scala keyword in backticks, allowing you to define a variable called match
,
a method called def
, a class called package
, etc.
Please do not use this feature unless it is absolutely necessary!
Here is some confusing code that should get you fired after a code review:
abstract class `class`(`match`: String) { def `def` = `match` match { case "three" => 3 case _ => Unit } }
Following is another example of abusing backticks.
The new
class defines a parametric method called new
.
We will discuss parametrics in the
Parametric Types lecture of the
Intermediate Scala course.
scala> class `new` { def `new`[`new`](`new`: `new`): `new` = `new` } defined class new
scala> new `new`().`new`(new `new`) res0: new = new@1a891add
import Statements
Import statements can reference specific classes:
import scala.collection.immutable.List
... or several classes:
import scala.collection.immutable.{List, Seq, Map}
... or all classes in a package (the underscore is often used as a wildcard in Scala):
import scala.collection.immutable._
The scala
package name can be omitted if there is no ambiguity with other packages of the same name.
import collection.immutable.List
Classes and packages can be renamed.
Here we rename the Java List
to JList
,
so the Scala List
can also be imported without a naming conflict.
import java.util.{ List => JList } import collection.{ immutable => cim } import cim.List

You can also hide imported class names by renaming them to underscore (_
).
As Yoda said, there is no Try
, there is only Do
, or DoNot
.
The Yoda He Is exercise in the
Try and try/catch/finally
lecture will have you work through this intriguing Scala code.
import scala.util.{Try => _, Success => Do, Failure => DoNot}
Locally Scoped imports
Unlike Java, where import
statements are all placed at the top of source files,
import
statements in Scala should be located in the most local scope practical.
The sample code for this lecture can be found in
courseNotes/
.
The following code is an example of how Scala can be used to extend Java’s capabilities.
object TimedTask { import java.util.{Timer, TimerTask}
def apply(intervalSeconds: Int=1)(op: => Unit): Unit = { val task = new TimerTask { def run = op } val timer = new Timer timer.schedule(task, 0L, intervalSeconds*1000L) } }
object TimedDemo extends App { import java.util.Date
TimedTask(1)(println(s"Hello, world! ${new Date}")) }
The TimedTask.apply
method above accepts two parameters:
the number of seconds between invocations of a closure
(intervalSeconds
), and a closure (op
) to run periodically.
I am not going to explain the rest of this program right now,
I just want you to see how the import
statements have been scoped within object
s.
The Closures
lecture later in this course will explain what a closure is.
We can run the TimedDemo
entry point at a console prompt with:
scala> sbt ~"runMain TimedDemo" Loading /usr/share/sbt/bin/sbt-launch-lib.bash [info] Loading global plugins from /home/mslinn/.sbt/0.13/plugins [info] Loading project definition from /var/work/course_scala_intro_code/courseNotes/project [info] Set current project to scalaIntroCourse (in build file:/var/work/course_scala_intro_code/courseNotes/) Hello, world! Sun Dec 29 10:30:51 PST 2013 Hello, world! Sun Dec 29 10:30:52 PST 2013 Hello, world! Sun Dec 29 10:30:53 PST 2013 Hello, world! Sun Dec 29 10:30:54 PST 2013 Hello, world! Sun Dec 29 10:30:55 PST 2013 Hello, world! Sun Dec 29 10:30:56 PST 2013 ^C
imports Can Enable Advanced Scala Language Features
The scala.language
object controls the language features available to the programmer.
Each of these features has to be explicitly imported into the current scope to become available.
In this way an organization can control the nature of the Scala code that is written,
by mandating or disallowing these imports.
import scala.language.postfixOps List(1, 2, 3) reverse
To enable all language features:
import scala.language._
The language features that can be enabled are:
-
dynamics
adds developer driven dynamic binding (dynamic dispatch) and gives a subset of the features of dynamic typing to Scala, via the Dynamic trait. This feature is not described further in this course. -
postfixOps
enables postfix operators. This feature enables an alternative writing style, which may be more natural in some circumstances, and is described this course. -
reflectiveCalls
enables structural types. This feature is described in detail in the Intermediate Scala course. -
implicitConversions
enables defining implicit methods and members. This feature is described in detail in the Intermediate Scala course. -
higherKinds
enables writing higher-kinded types. -
existentials
enables writing existential types. -
experimental
contains newer features that have not yet been tested in production and may be significantly changed or removed in future versions of Scala. The only features in the experimental category of Scala version 2.13 is the macro capability. This feature is not described in this course; the Scala macro facility completely changed for Scala 3.
© Copyright 1994-2024 Michael Slinn. All rights reserved.
If you would like to request to use this copyright-protected work in any manner,
please send an email.
This website was made using Jekyll and Mike Slinn’s Jekyll Plugins.