Upper Bounds
A simple declaration of T
could be any type. Sometimes, we need to limit it to only be certain types. The simplest way to do that is to declare T
a bit like a class or interface, using a colon and a type to declare what T
must inherit from:
open class Thingy
open class Animal : Thingy()
class Frog : Animal()
class Axolotl : Animal()
interface Transport<T : Thingy> {
abstract fun getPassenger(): T
}
data class Van(val animal: Animal) : Transport<Animal> {
override fun getPassenger() = animal
}
fun main() {
val kermit = Frog()
val critterCarrier = Van(kermit)
println(critterCarrier.getPassenger()::class)
}
Now Transport
cannot transport anything — it is limited to instances of Thingy
. Since an Animal
is a Thingy
, we can still transport animals. But we cannot create a Transport
of String
, because a String
does not extend from Thingy
. If we try anyway:
open class Thingy
interface Transport<T : Thingy> {
abstract fun getPassenger(): T
}
data class StringVehicle(val value: String) : Transport<String> {
override fun getPassenger() = value
}
…we wind up with a compile error:
error: type argument is not within its bounds: should be subtype of 'Test.Thingy'
data class StringVehicle(val value: String) : Transport<String> {
^
Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.