How to manually declare a type when creating a Scala collection instance

Note: This is an excerpt from the Scala Cookbook. This is one of the shorter recipes, Recipe 10.5, “How to manually declare a type when creating a collection instance.”

Problem

You want to create a collection of mixed types that share a common hierarchy, and Scala isn’t automatically assigning the type you want.

Solution

In the following example, if you don’t specify a type, Scala automatically assigns a type of Double to the list:

scala> val x = List(1, 2.0, 33D, 400L)
x: List[Double] = List(1.0, 2.0, 33.0, 400.0)

If you’d rather have the collection be of type Number, specify the type in brackets before your collection declaration:

scala> val x = List[Number](1, 2.0, 33D, 400L)
x: List[java.lang.Number] = List(1, 2.0, 33.0, 400)

You can also go further up the type hierarchy and declare the type to be AnyVal:

scala> val x = List[AnyVal](1, 2.0, 33D, 400L)
x: List[AnyVal] = List(1, 2.0, 33.0, 400)

Discussion

By manually specifying a type — in this case Number — you control the collection type. This is useful any time a list contains mixed types or multiple levels of inheritance.

For instance, given this type hierarchy:

trait Animal
trait FurryAnimal extends Animal
case class Dog(name: String) extends Animal
case class Cat(name: String) extends Animal

create a sequence with a Dog and a Cat:

scala> val x = Array(Dog("Fido"), Cat("Felix"))
x: Array[Product with Serializable with Animal] = Array(Dog(Fido), Cat(Felix))

As shown, Scala assigns a type of Product with Serializable with Animal. If you want the type to be Array[Animal], manually specify the desired type:

scala> val x = Array[Animal](Dog("Fido"), Cat("Felix"))
x: Array[Animal] = Array(Dog(Fido), Cat(Felix))

This may not seem like a big deal, but imagine declaring a class with a method that returns this array:

class AnimalKingdom {
    def animals = Array(Dog("Fido"), Cat("Felix"))
}

When you generate the Scaladoc for this class, the animals method will show the Product with Serializable in its Scaladoc:

def animals: Array[Product with Serializable with Animal]

If you’d rather have it appear like this in your Scaladoc:

def animals: Array[Animal]

manually assign the type, as shown in the Solution:

def animals = Array[Animal](Dog("Fido"), Cat("Felix"))