Package Objects

Martin Odersky, Lex Spoon

September 15, 2010

Until 2.8, the only things you could put in a package were classes, traits, and standalone objects. These are by far the most common definitions that are placed at the top level of a package, but version 2.8 of the Scala programming language doesn't limit you to just those. Any kind of definition that you can put inside a class, you can also put at the top level of a package. If you have some helper method you'd like to be in scope for an entire package, go ahead and put it right at the top level of the package.

To do so, put the definitions in a package object. Each package is allowed to have one package object. Any definitions placed in a package object are considered members of the package itself.

An example is shown in the following listings. Assume first a class Fruit and three Fruit objects in a package gardening.fruits:

// in file gardening/fruits/Fruit.scala
package gardening.fruits
case class Fruit(name: String, color: String)
object apple extends Fruit("Apple""green")
object plum extends Fruit("Plum""blue")
object banana extends Fruit("Banana""yellow"

Now assume you want to place a variable planted and a method showFruit directly into package gardening. Here's how this is done:

// in file gardening/fruits/package.scala
package gardening
package object fruits {
  val planted = List(apple, plum, banana)               
  def showFruit(fruit: Fruit) {
    println(fruit.name +"s are "+ fruit.color)
  }
}

File gardening/fruits/package.scala holds a package object for package gardening.fruits. Syntactically, a package object looks much like a plain object definition. The only difference is that it includes the package keyword. It's a package object, not a plain object. The contents of the curly braces can include any definitions you like. In the listing above case, the package object includes the planted variable and the showFruit utility method.

Given that definition, any other code in the same package can import the method just like it would import a class. For example, the following object PrintPlanted imports planted and showFruit in exactly the same way it imports class Fruit, using a wildcard import on package gardening.fruits:

// in file PrintPlanted.scala
import gardening.fruits._
object PrintPlanted {
  def main(args: Array[String]) {
    for (fruit: Fruit <- fruits.planted) {
      showFruit(fruit)
    }
  }
}

Package objects can contain arbitrary definitions, not just variable and method definitions. For instance, they are also frequently used to hold package-wide type aliases and implicit conversions. Package objects can even inherit Scala classes and traits.