🎓 A1Learner
🔍
0 of 48 lessons completed

Scala Upper Bounds

An upper bound is a limit on a type parameter that says how high a type may go. It requires every type used to be that type or a type below it.

A bounded method can use the animal name

animalName accepts any animal type. It reads the name that every animal has.

class Animal(val name: String)
class Dog(name: String) extends Animal(name)
class Cat(name: String) extends Animal(name)
def animalName[T <: Animal](a: T): String = a.name
@main def main(): Unit =
  println(animalName(Dog("Rex")))
  println(animalName(Cat("Mimi")))

A bounded method can return the first animal

first takes a list of one animal type. It returns the first item of that same type.

class Animal(val name: String)
class Dog(name: String) extends Animal(name)
class Cat(name: String) extends Animal(name)
def first[T <: Animal](xs: List[T]): T = xs.head
@main def main(): Unit =
  println(first(List(Dog("Rex"), Dog("Max"))).name)
  println(first(List(Cat("Mimi"))).name)

A bounded method can name a whole list

names maps over a list of one animal type. Every item gives its name.

class Animal(val name: String)
class Dog(name: String) extends Animal(name)
class Cat(name: String) extends Animal(name)
def names[T <: Animal](xs: List[T]): List[String] = xs.map(_.name)
@main def main(): Unit =
  println(names(List(Dog("Rex"), Dog("Max"))))
  println(names(List(Cat("Mimi"), Cat("Luna"))))

Example

class Animal(val name: String)
class Dog(name: String) extends Animal(name)
class Cat(name: String) extends Animal(name)
def first[T <: Animal](xs: List[T]): T = xs.head
def names[T <: Animal](xs: List[T]): List[String] = xs.map(_.name)
@main def main(): Unit =
  val dogs = List(Dog("Rex"), Dog("Max"))
  println(first(dogs).name)
  println(names(dogs))
  println(names(dogs).length)

Key points

  • Bound syntax: T <: Animal means T is Animal or a type that extends Animal.
  • Shared members: inside the method, values of type T can use Animal members such as name.
  • Compile-time check: a type outside the bound is rejected before the program runs.
  • Lists too: List[T] with the same bound holds only animals or their subtypes.
  • Reuse: one bounded method serves Dog, Cat, and every other animal type.

In this example, first returns the first dog from the list, names builds a list of both dog names, and the length of that name list is printed.

Note

the bound is a ceiling, so a type above Animal cannot be used.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Scastie

Exercise

Why does a method use an upper bound T <: Animal?