In Scala, type bounds are used to restrict the types that can be used as type parameters in generic classes, traits, or methods. Type bounds provide a way to specify constraints on type parameters, allowing you to define more specific behavior or requirements for the types used.
There are two main types of type bounds in Scala: upper bounds and lower bounds.
1. Upper Bounds : Upper bounds restrict the type parameter to be a subtype of a specified type. They are denoted by the `
<:` symbol. For example, `
A <: B` means that the type parameter `
A` must be a subtype of `
B`.
class Container[A <: Number] {
// ...
}
val container1 = new Container[Int] // Valid, Int is a subtype of Number
val container2 = new Container[String] // Invalid, String is not a subtype of Number
In this example, the `
Container` class has an upper bound of `
Number`. This means that the type parameter `
A` can only be a subtype of `
Number` or the `
Number` class itself. Therefore, `
Container[Int]` is valid because `
Int` is a subtype of `
Number`, but `
Container[String]` is invalid because `
String` is not a subtype of `
Number`.
2. Lower Bounds : Lower bounds restrict the type parameter to be a supertype of a specified type. They are denoted by the `
>:` symbol. For example, `
A >: B` means that the type parameter `
A` must be a supertype of `
B`.
class Printer[A >: String] {
// ...
}
val printer1 = new Printer[Any] // Valid, Any is a supertype of String
val printer2 = new Printer[Int] // Invalid, Int is not a supertype of String
In this example, the `
Printer` class has a lower bound of `
String`. This means that the type parameter `
A` must be a supertype of `
String` or the `
String` class itself. Therefore, `
Printer[Any]` is valid because `
Any` is a supertype of `
String`, but `
Printer[Int]` is invalid because `
Int` is not a supertype of `
String`.
Type bounds are useful when you want to specify constraints on the types used as type parameters. They allow you to write more generic code that works with a restricted set of types, providing additional compile-time safety and preventing inappropriate type usages.
Some common use cases for type bounds include :* Restricting the types that can be used with certain operations or methods.
* Ensuring that a generic class or trait can only be instantiated or extended with specific types.
* Defining generic methods that can operate on a specific subset of types.
Type bounds help improve type safety and enable more precise type inference, leading to more robust and concise code in Scala.