4.16. Creating Inner Classes

Problem

You want to create a class as an inner class to help keep the class out of your public API, or to otherwise encapsulate your code.

Solution

Declare one class inside another class. In the following example, a case class named Thing is declared inside of a class named PandorasBox:

class PandorasBox {

  case class Thing (name: String)

  var things = new collection.mutable.ArrayBuffer[Thing]()
  things += Thing("Evil Thing #1")
  things += Thing("Evil Thing #2")

  def addThing(name: String) { things += new Thing(name) }

}

This lets users of PandorasBox access the collection of things inside the box, while code outside of PandorasBox generally doesn’t have to worry about the concept of a Thing:

object ClassInAClassExample extends App {

  val p = new PandorasBox
  p.things.foreach(println)

}

As shown, you can access the things in PandorasBox with the things method. You can also add new things to PandorasBox by calling the addThing method:

p.addThing("Evil Thing #3")
p.addThing("Evil Thing #4")

Discussion

The concept of a “class within a class” is different in Scala than in Java. As described on the official Scala website, “Opposed to Java-like languages where such inner classes are members of the enclosing class, in Scala, such inner classes are bound to the outer object.” The following code demonstrates this:

object ClassInObject extends App {

  // inner classes are bound to the object
  val oc1 = new OuterClass
  val oc2 = new OuterClass
  val ic1 = new oc1.InnerClass
  val ic2 = new oc2.InnerClass
  ic1.x = 10
  ic2.x = 20
  println(s"ic1.x = ${ic1.x}")
  println(s"ic2.x = ${ic2.x}")
}

class OuterClass {
  class InnerClass {
    var x = 1
  }
}

Because inner classes are bound to their object instances, when that code is run, it prints the following output:

ic1.x = 10
ic2.x = 20

There are many other things you can do with inner classes, such as include a class inside an object or an object inside a class:

object InnerClassDemo2 extends App {

  // class inside object
  println(new OuterObject.InnerClass().x)

  // object inside class
  println(new OuterClass().InnerObject.y)

}

object OuterObject {
  class InnerClass {
    var x = 1
  }
}

class OuterClass {
  object InnerObject {
    val y = 2
  }
}

See Also

The Scala website has a page on Inner Classes.

Get Scala Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.