Scala Book

Enumerations (and a Complete Pizza Class)

Language

If we demonstrate enumerations next, we can also show you what an example Pizza class looks like when written in an object-oriented manner. So that’s the path we’ll take.

Enumerations are a useful tool for creating small groups of constants, things like the days of the week, months in a year, suits in a deck of cards, etc., situations where you have a group of related, constant values.

Because we’re jumping ahead a little bit, we’re not going to explain this syntax too much, but this is how you create an enumeration for the days of a week:

sealed trait DayOfWeek
case object Sunday extends DayOfWeek
case object Monday extends DayOfWeek
case object Tuesday extends DayOfWeek
case object Wednesday extends DayOfWeek
case object Thursday extends DayOfWeek
case object Friday extends DayOfWeek
case object Saturday extends DayOfWeek

As shown, just declare a base trait and then extend that trait with as many case objects as needed.

Similarly, this is how you create an enumeration for the suits in a deck of cards:

sealed trait Suit
case object Clubs extends Suit
case object Spades extends Suit
case object Diamonds extends Suit
case object Hearts extends Suit

We’ll discuss traits and case objects later in this book, but if you’ll trust us for now that this is how you create enumerations, we can then create a little OOP version of a Pizza class in Scala.

Given that (very brief) introduction to enumerations, we can now create pizza-related enumerations like this:

sealed trait Topping
case object Cheese extends Topping
case object Pepperoni extends Topping
case object Sausage extends Topping
case object Mushrooms extends Topping
case object Onions extends Topping

sealed trait CrustSize
case object SmallCrustSize extends CrustSize
case object MediumCrustSize extends CrustSize
case object LargeCrustSize extends CrustSize

sealed trait CrustType
case object RegularCrustType extends CrustType
case object ThinCrustType extends CrustType
case object ThickCrustType extends CrustType

Those enumerations provide a nice way to work with pizza toppings, crust sizes, and crust types.

A sample Pizza class

Given those enumerations, we can define a Pizza class like this:

class Pizza (
    var crustSize: CrustSize = MediumCrustSize, 
    var crustType: CrustType = RegularCrustType
) {

    // ArrayBuffer is a mutable sequence (list)
    val toppings = scala.collection.mutable.ArrayBuffer[Topping]()

    def addTopping(t: Topping): Unit = toppings += t
    def removeTopping(t: Topping): Unit = toppings -= t
    def removeAllToppings(): Unit = toppings.clear()

}

If you save all of that code — including the enumerations — in a file named Pizza.scala, you’ll see that you can compile it with the usual command:

$ scalac Pizza.scala

That code will create a lot of individual files, so we recommend putting it in a separate directory.

There’s nothing to run yet because this class doesn’t have a main method, but …

A complete Pizza class with a main method

If you’re ready to have some fun, copy all of the following source code and paste it into a file named Pizza.scala:

import scala.collection.mutable.ArrayBuffer

sealed trait Topping
case object Cheese extends Topping
case object Pepperoni extends Topping
case object Sausage extends Topping
case object Mushrooms extends Topping
case object Onions extends Topping

sealed trait CrustSize
case object SmallCrustSize extends CrustSize
case object MediumCrustSize extends CrustSize
case object LargeCrustSize extends CrustSize

sealed trait CrustType
case object RegularCrustType extends CrustType
case object ThinCrustType extends CrustType
case object ThickCrustType extends CrustType

class Pizza (
    var crustSize: CrustSize = MediumCrustSize, 
    var crustType: CrustType = RegularCrustType
) {

    // ArrayBuffer is a mutable sequence (list)
    val toppings = ArrayBuffer[Topping]()

    def addTopping(t: Topping): Unit = toppings += t
    def removeTopping(t: Topping): Unit = toppings -= t
    def removeAllToppings(): Unit = toppings.clear()

    override def toString(): String = {
        s"""
        |Crust Size: $crustSize
        |Crust Type: $crustType
        |Toppings:   $toppings
        """.stripMargin
    }
}

// a little "driver" app
object PizzaTest extends App {
   val p = new Pizza
   p.addTopping(Cheese)
   p.addTopping(Pepperoni)
   println(p)
}

Notice how you can put all of the enumerations, a Pizza class, and a PizzaTest object in the same file. That’s a very convenient Scala feature.

Next, compile that code with the usual command:

$ scalac Pizza.scala

Now, run the PizzaTest object with this command:

$ scala PizzaTest

The output should look like this:

$ scala PizzaTest

Crust Size: MediumCrustSize
Crust Type: RegularCrustType
Toppings:   ArrayBuffer(Cheese, Pepperoni)

That code combines several different concepts — including two things we haven’t discussed yet in the import statement and the ArrayBuffer — but if you have experience with Java and other languages, hopefully it’s not too much to throw at you at one time.

At this point we encourage you to work with that code as desired. Make changes to the code, and try using the removeTopping and removeAllToppings methods to make sure they work the way you expect them to work.

Contributors to this page: