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.