How to put common code in Scala package objects

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 6.7, “How to put common code in Scala package objects.”

Problem

You want to make Scala functions, fields, and other code available at a package level, without requiring a class or object.

Solution

Put the code you want to make available to all classes within a package in a package object.

By convention, put your code in a file named package.scala in the directory where you want your code to be available. For instance, if you want your code to be available to all classes in the com.alvinalexander.myapp.model package, create a file named package.scala in the com/alvinalexander/myapp/model directory of your project. In the package.scala source code, remove the word model from the end of the package statement, and use that name to declare the name of the package object. Including a blank line, the first three lines of your file will look like this:

package com.alvinalexander.myapp

package object model {

Now write the rest of your code as you normally would. The following example shows how to create a field, method, enumeration, and type definition in your package object:

package com.alvinalexander.myapp

package object model {

    // field
    val MAGIC_NUM = 42

    // method
    def echo(a: Any) { println(a) }

    // enumeration
    object Margin extends Enumeration {
        type Margin = Value
        val TOP, BOTTOM, LEFT, RIGHT = Value
    }

    // type definition
    type MutableMap[K, V] = scala.collection.mutable.Map[K, V]
    val MutableMap = scala.collection.mutable.Map

}

You can now access this code directly from within other classes, traits, and objects in the package com.alvinalexander.myapp.model as shown here:

package com.alvinalexander.myapp.model

object MainDriver extends App {

    // access our method, constant, and enumeration
    echo("Hello, world")
    echo(MAGIC_NUM)
    echo(Margin.LEFT)

    // use our MutableMap type (scala.collection.mutable.Map)
    val mm = MutableMap("name" -> "Al")
    mm += ("password" -> "123")
    for ((k,v) <- mm) printf("key: %s, value: %s\n", k, v)

}

Discussion

The most confusing part about package objects is where to put them, along with what their package and object names should be.

Where to put them isn’t too hard; by convention, create a file named package.scala in the directory where you want your code to be available. In the example shown, I want the package code to be available in the com.alvinalexander.myapp.model package, so I put the file package.scala in the com/alvinalexander/myapp/model source code directory:

+-- com
    +-- alvinalexander
        +-- myapp
            +-- model
                +-- package.scala

In regards to the first few lines of the package.scala source code, simply start with the usual name of the package:

package com.alvinalexander.myapp.model

Then take the name of the last package level (model) off that statement, leaving you with this:

package com.alvinalexander.myapp

Then use that name (model) as the name of your package object:

package object model {

As shown earlier, the first several lines of your package.scala file will look like this:

package com.alvinalexander.myapp
package object model {

The Scala package object documentation states, “Any kind of definition that you can put inside a class, you can also put at the top level of a package.” In my experience, package objects are a great place to put methods and functions that are common to the package, as well as constants, enumerations, and implicit conversions.

As described in the second page of the Scala package object documentation, “The standard Scala package also has its package object. Because scala._ is automatically imported into every Scala file, the definitions of this object are available without prefix.” If you create something like a StringBuilder or Range, you’re using this code.

See Also

Scala’s root package object is full of type aliases, like these:

type Throwable = java.lang.Throwable
type Exception = java.lang.Exception
type Error     = java.lang.Error

type RuntimeException     = java.lang.RuntimeException
type NullPointerException = java.lang.NullPointerException
type ClassCastException   = java.lang.ClassCastException

Like the Predef object, its source code is worth looking at if you want to know more about how Scala works. You can find its source by following the “source” link on its Scaladoc page.

  • An introduction to package objects
  • The Scala package object