Skip to content
AgileLogics
4 min read

Packages and Imports

Prerequisites: Objects and companion objects

Packages

A package groups related code and gives it a namespace. Declare it at the top of a file:

// illustrative
package com.example.shop.billing

case class Invoice(id: Int, total: BigDecimal)

def formatInvoice(i: Invoice): String = s"#${i.id}: ${i.total}"

By convention, packages use reversed domain names, and the folder structure mirrors them (src/main/scala/com/example/shop/billing/).

Imports

import scala.collection.mutable
import scala.util.{Try, Success as Ok}
import scala.math.{Pi, sqrt}
import java.time.LocalDate

@main def imports(): Unit =
  val buffer = mutable.ListBuffer(1, 2)
  buffer += 3
  println(buffer)
  println(Try(1) == Ok(1))
  println(sqrt(Pi * Pi))
  println(LocalDate.of(2025, 4, 22).getDayOfWeek)
ListBuffer(1, 2, 3)
true
3.141592653589793
TUESDAY
  • import a.b.C — one name; import a.b.* — everything in a.b.
  • {A, B} — several names; Name as Other renames on import.
  • Importing a package (scala.collection.mutable) lets you write mutable.ListBuffer, making it obvious a collection is mutable.
  • Imports can go anywhere — inside a method, to keep them local.

Visibility

Modifier Visible to
(none) everyone — public is the default
private the enclosing class or object (and its companion)
protected the class and its subclasses
private[shop] everything inside the package shop

Export clauses

Scala 3's export re-exports members of another object — composition without boilerplate:

class Logger:
  def info(msg: String): Unit = println(s"INFO $msg")

class Service:
  private val logger = Logger()
  export logger.info

@main def exports(): Unit =
  Service().info("started")
INFO started