Groovy Operators

Control Statements

Groovy File Handling

Groovy Error & Exceptions

Groovy Multithreading

Groovy Synchronization

Groovy - Bound Type Parameters



Bound Type Parameter provides a way to restrict the type of generics used in Groovy classes or methods. We can define either a lower bound using super or upper bound using extends for the type parameter. This kind of functionality is useful when we want to use only a set of types or types following a certain hiearchy.

Upper Bound Type Parameter

Upper Bound Type parameter restrict type parameter to be a subtype of particular class/interface.

Example.groovy

interface Drawable {
   void draw()
}

class Circle implements Drawable {
   void draw() { println "Circle Drawn" }
}

class Rectangle implements Drawable {
   void draw() { println "Rectangle drawn" }
}

class Canvas<T extends Drawable> {
   void drawShape(T shape) {
      // as shape is drawable, we can call draw() method
      shape.draw() 
   }
}

// create a circle
def circle = new Canvas<Circle>()
// prints Circle Drawn
circle.drawShape(new Circle())

def rectangle = new Canvas<Rectangle>()
// prints Rectangle Drawn
rectangle.drawShape(new Rectangle()) 


// String is not drawable
def string = new Canvas<String>()

// below line throws error as String is not drawable
string.drawShape("Test") 

Output

When we run the above program, we will get the following result.

Circle Drawn
Rectangle drawn
Caught: groovy.lang.MissingMethodException: No signature of method: Canvas.drawShape() is applicable for argument types: (java.lang.String) values: [Test]
Possible solutions: drawShape(Drawable)

Lower Bound Type Parameter

Lower Bound Type parameter restrict type parameter to be a supertype of particular class. For example, we want to use only integers. In below example, we're restricting our method to accept either integers or its subtype as shown below −

Example.groovy

void process(List<? super Integer> list) {
   list.add(10)
   list.add(new Integer(20))
   list.add("ABC") 
}

def listOfIntegers = new ArrayList<Integer>()
process(listOfIntegers)
// prints [10, 20, ABC]
println listOfIntegers 

def listOfNumbers = new ArrayList<Number>()
process(listOfNumbers)
// prints [10, 20, ABC]
println listOfNumbers

def listOfObjects = new ArrayList<Object>()
process(listOfObjects)
// prints [10, 20, ABC]
println listOfObjects 

def listOfStrings = new ArrayList<String>()
process(listOfStrings)
// prints [10, 20, ABC]
println listOfStrings 

Output

When we run the above program, we will get the following result.

[10, 20, ABC]
[10, 20, ABC]
[10, 20, ABC]
[10, 20, ABC]

But as evident from the output, due to type erasure, Groovy bypasses the type restriction. But using generic improves the code readablity and the code clarity.

Advertisements