Packages and Imports
When we changed our code to compile we had to add many import statements to it. In this section we learn about them.
We've seen that one name can shadow another. This can cause problems in larger programs as many parts of a program may want to put a common name to different uses. We can create scopes to hide names from the outside, but we must still deal with names defined at the top-level.
We have the same problem in natural language. For example, if both your brother and friend were called "Ziggy" you would have to qualify which one you meant when you used their name. Perhaps you could tell from context, or perhaps your friend was "Ziggy S" and your brother was just "Ziggy".
In Scala we can use packages to organise names. A package creates a scope for names defined at the top-level. All top-level names within the same package are defined in the same scope. To bring names in a package into another scope we must import them.
Creating a package is simple: we write
package <name>
at the top of the file, replacing <name>
with the name of our package.
You can't define packages in a worksheet.
To get the following code to work you must put the code within the package example
into a file and compile it.
When we want to use names defined in a package we use an import
statement, specifying the package name followed by *
for all names, or the just the name we want if we only want one or a few names.
Here's an example.
Let's start by defining some names within a package.
package example
object One {
val one = 1
}
object Two {
val two = 2
}
object Three {
val three = 3
}
Now to bring these names into scope in a different file we must import them. We could import just one name.
import example.One
One.one
Or both One
and Two
.
import example.{One, Two}
One.one + Two.two
Or all the names in example
.
import example.*
One.one + Two.two + Three.three
In Scala we can also import just about anything that defines a scope, including objects.
So the following code brings one
into scope.
import example.One.*
one
Import Syntax
To import names from a package we use the following syntax:
import <package>.*
, imports all the names in the package. This is known as a wildcard import.import <package>._
is the Scala 2 syntax for a wildcard import.import <package>.<name>
to import just one name.import <package>.{<name1>, <name2>, ...}
to import more than one name.
Package Organisation
Packages stop top-level names from colliding, but what about collisions between package names?
It's common to organise packages in a hierarchy, which helps to avoid collisions.
For example, in Doodle the package core
is defined within the package doodle
.
When we use the statement
import doodle.core.*
we're indicating we want the package core
within the package doodle
, and not some other package that might be called core
.
To define such a package we use the syntax
package doodle.core