WalzoneInterview Prep
📞 Interviewing soon? Practice with a realistic AI mock phone interview — it calls you, then scores you. First 15 min FREE →

Scala · Intermediate · question 28 of 100

How are type bounds used in Scala? Explain the difference between upper and lower type bounds.?

📕 Buy this interview preparation book: 100 Scala questions & answers — PDF + EPUB for $5

Type bounds are a way to define restrictions on the types that can be used as generic parameters in Scala, allowing you to create code that enforces certain relationships or constraints between types. There are two kinds of type bounds in Scala: upper type bounds and lower type bounds.

1. Upper Type Bounds:

Upper type bounds define an upper limit on a type parameter. They are specified using the ‘<:‘ symbol. If you define an upper type bound for a type parameter ‘T‘, it means that T can be any type that is a subtype of the given bound.

For example, let’s consider a simple trait hierarchy and a generic class that takes a type parameter with an upper type bound:

trait Animal
trait Mammal extends Animal
trait Reptile extends Animal

class PetBox[T <: Animal](val pet: T)

val dogBox = new PetBox[Mammal](new Mammal { })
val lizardBox = new PetBox[Reptile](new Reptile { })

Here, ‘Animal‘ is a trait that ‘Mammal‘ and ‘Reptile‘ extend. The class ‘PetBox‘ takes a type parameter ‘T‘, where ‘T‘ is a subtype of ‘Animal‘. This means that you can create instances of ‘PetBox‘ with ‘Mammal‘ and ‘Reptile‘, but not with a type that is not a subtype of ‘Animal‘.

2. Lower Type Bounds:

Lower type bounds define a _lower_ limit on a type parameter by specifying a lower bound. They are specified using the ‘>:‘ symbol. If you define a lower type bound for a type parameter ‘U‘, it means that U can be any type that is a supertype of the given bound.

Here’s an example of a lower type bound in action:

trait Animal {
  def speak: String
}

class Mammal() extends Animal {
  def speak: String = "Mammal noise"
}

class Reptile() extends Animal {
  def speak: String = "Reptile noise"
}

class AnimalHandler[T >: Mammal](val animal: T)

val handler1 = new AnimalHandler(new Mammal) // OK
val handler2 = new AnimalHandler(new Animal {}) // OK, because Animal is a supertype of Mammal

// This would not compile, because Reptile is not a supertype of Mammal:
// val handler3 = new AnimalHandler(new Reptile)

Here, ‘AnimalHandler‘ takes a type parameter ‘T‘ with a lower type bound of ‘Mammal‘ (‘T >: Mammal‘). This means you can create an instance of ‘AnimalHandler‘ with ‘Mammal‘ or its supertypes, but not with a type that is not a supertype of ‘Mammal‘.

In summary, upper type bounds use the ‘<:‘ symbol to enforce a type parameter to be a subtype (or equal) to a given type, while lower type bounds use ‘>:‘ to require a type parameter to be a supertype (or equal) to a given type. Using these concepts, one can create more expressive and flexible generic components in Scala.

Reading is step one. Saying it out loud is the interview. Our AI interviewer calls your phone and runs a realistic Scala interview — then scores it.
📞 Practice Scala — free 15 min
📕 Buy this interview preparation book: 100 Scala questions & answers — PDF + EPUB for $5

All 100 Scala questions · All topics