In my previous post, I have discussed about Scala Variance in detail. In this post, we are going to discuss about “Scala Type Bounds”.
What is Type Bound in Scala?
In Scala, Type Bounds are restrictions on Type Parameters or Type Variable. By using Type Bounds, we can define the limits of a Type Variable.
Advantage of Scala Type Bounds
Scala Type Bounds give us the following benefit:
- Type-Safe Application Development.
Scala Type Bounds
Scala supports the following Type Bounds for Type Variables:
- Scala Upper Bounds
- Scala Lower Bounds
- Scala View Bounds
We are going to discuss these concepts in detail with examples in next sections.
Scala Upper Bounds
In Scala, we can define Upper Bound on Type Parameter as shown below:
Description:-
Here T is a Type Parameter ans S is a type. By declaring Upper Bound like “[T <: S]” means this Type Parameter T must be either same as S or Sub-Type of S.
Example-1:-
[T <: Ordered[T]]
Here We have defined Upper Bound from Type Parameter T to Type Ordered[T]. Then T much be either Ordered or subtype of Ordered type.
Example-2:-
Write a Scala program to demonstrate Scala Upper Bound.
class Animal
class Dog extends Animal
class Puppy extends Dog
class AnimalCarer{
def display [T <: Dog](t: T){
println(t)
}
}
object ScalaUpperBoundsTest {
def main(args: Array[String]) {
val animal = new Animal
val dog = new Dog
val puppy = new Puppy
val animalCarer = new AnimalCarer
//animalCarer.display(animal)
animalCarer.display(dog)
animalCarer.display(puppy)
}
}
This program works fine with commenting the following line.
//animalCarer.display(animal)
If we uncomment this line and try to run it, we will get compilation error. Because we have defined Upper Bound as shown below:
class AnimalCarer{
def display [T <: Dog](t: T){
println(t)
}
}
Here we have defined “[T <: Dog]” that means “display” method accepts only either Dog class object or subclass type (i.e. Puppy) of Dog Class. That's why if we pass Dog Super class, we will get “Type Mismatch” compilation error.
Scala Lower Bounds
In Scala, we can define Lower Bound on Type Parameter as shown below:
Description:-
Here T is a Type Parameter ans S is a type. By declaring Lower Bound like “[T >: S]” means this Type Parameter T must be either same as S or Super-Type of S.
Example-1:-
[T >: Ordered[T]]
Here We have defined Lower Bound from Type Parameter T to Type Ordered[T]. Then T much be either Ordered or supertype of Ordered type.
Example-2:-
class Animal
class Dog extends Animal
class Puppy extends Animal
class AnimalCarer{
def display [T >: Puppy](t: T){
println(t)
}
}
object ScalaLowerBoundsTest {
def main(args: Array[String]) {
val animal = new Animal
val dog = new Dog
val puppy = new Puppy
val animalCarer = new AnimalCarer
animalCarer.display(animal)
animalCarer.display(puppy)
animalCarer.display(dog)
}
}
Here Dog is not a subtype of Puppy, but still this program works fine because Dog is a subtype of Animal and we have defined “Lower Bound” on Type Parameter T as shown below:
class AnimalCarer{
def display [T >: Puppy](t: T){
println(t)
}
}
If we remove Lower Bound definition in this class, then we will get some compilation errors.
Scala View Bounds
In Scala, View Bound is used when we want to use existing Implicit Conversions automatically. We can define View Bound on Type Parameter as shown below:
Description:-
In some scenarios, we need to use some Implicit conversions automatically to solve our problem statement. We can use Scala’s View Bounds to utilize these Implicits.
Example:-
Write a Scala program to compare Strings with Relational operators(like Int’s 10 > 12).
class Person[T <% Ordered[T]](val firstName: T, val lastName: T) {
def greater = if (firstName > lastName) firstName else lastName
}
object ScalaViewBoundsTest {
def main(args: Array[String]) {
val p1 = new Person("Rams","Posa")
val p2 = new Person("Chintu","Charan")
println(p1.greater)
println(p2.greater)
}
}
Output:-
Rams
Chintu
If we don’t use Scala’s View Bound operator “<%”, then we will get the following error message.
error: value > is not a member of type parameter T
That’s it all about Scala Upper Bounds, Lower Bounds and View Bounds. We will discuss some more Scala concepts in my coming posts.
Please drop me a comment if you like my post or have any issues/suggestions.
Hello Sir,
i amended the code below and surprise to me it is working.
class Animal
class Dog extends Animal
class Puppy extends Animal
class Puppy1 extends Animal
class Puppy2 extends Puppy
class AnimalCarer{
def display [T >: Puppy](t: T){
println(t)
}
}
val animal = new Animal
val dog = new Dog
val puppy = new Puppy
val puppy1 = new Puppy1
val puppy2 = new Puppy2
val animalCarer = new AnimalCarer
animalCarer.display(animal)
animalCarer.display(puppy)
animalCarer.display(puppy1)
animalCarer.display(puppy2)
animalCarer.display(dog)
It should not as the upper bound is Puppy.
Thanks for reading my tutorials. Let me check it and update the same soon.
Ram
hi sir can u suggest me good book for learning scala and play scala framework
Thanks to read my tutorials.
You can find those info in my bolog: https://rams4java.blogspot.co.uk/2016/02/top-5-play-framework-books-must-read.html
https://rams4java.blogspot.co.uk/2016/07/spring-boot-books-to-learn.html
Choose one of them depends on your experience. If you have any questions, please come back to me.
Ram
———–Scala Lower Bounds—————-
class Animal
class Puppy extends Animal
class SmallPuppy extends Puppy
class AnimalCarer{
def display [T >: Puppy](t: T){
println(t)
}
}
object ScalaLowerBoundsTest {
def main(args: Array[String]) {
val animal = new Animal
val sp = new SmallPuppy
val puppy = new Puppy
val animalCarer = new AnimalCarer
animalCarer.display(animal)
animalCarer.display(puppy)
animalCarer.display(sp)
}
}
animalCarer method accepts any class which is subclass of Puppy in LOWERBOUND example.
Is it fine?