Type Constraints
Part of the Object Oriented Programming section of Coddy's Kotlin journey. Lesson 39 of 57.
An upper bound restricts a type parameter. <T : Comparable<T>> accepts only types whose values can be compared with each other, so the function may use < and > on them:
fun <T : Comparable<T>> largest(a: T, b: T, c: T): T {
var best = a
if (b > best) best = b
if (c > best) best = c
return best
}Inside main:
println(largest(3, 9, 4))
println(largest("pear", "apple", "fig"))Output:
9
pearThe bound can be any class or interface, including your own. Inside the function, the bound's members are available, and the result still has the caller's exact type:
interface Priced {
val price: Int
}
data class Book(val title: String, override val price: Int) : Priced
data class Lamp(val watts: Int, override val price: Int) : Priced
fun <T : Priced> cheapest(items: List<T>): T? = items.minByOrNull { it.price }Inside main:
val book = cheapest(listOf(Book("Dune", 12), Book("Emma", 8)))
println(book?.title)
println(cheapest(listOf(Lamp(60, 30), Lamp(9, 45)))?.watts)Output:
Emma
60where lists several bounds for one type parameter; the type argument must satisfy all of them:
interface Named {
val name: String
}
data class City(override val name: String, val size: Int) : Named, Comparable<City> {
override fun compareTo(other: City) = size - other.size
}
fun <T> smallestFirst(items: List<T>): String where T : Named, T : Comparable<T> =
items.sorted().joinToString(" < ") { it.name }Inside main:
println(smallestFirst(listOf(City("Oslo", 700), City("Bergen", 290), City("Tromso", 77))))Output:
Tromso < Bergen < OsloWithout a bound, a type parameter may also be nullable, because its default bound is Any?. <T : Any> rules out nullable types, which is useful when null has a meaning of its own, such as "not found":
fun <T> describe(x: T) = "value: $x"
fun <T : Any> firstMatch(items: List<T>, test: (T) -> Boolean): T? {
for (item in items) if (test(item)) return item
return null
}Inside main:
println(describe(null))
println(firstMatch(listOf(4, 7, 10)) { it > 5 })
println(firstMatch(listOf("a", "b")) { it == "z" })
// firstMatch(listOf(1, null)) { true } // error: Int? does not satisfy T : AnyOutput:
value: null
7
nullChallenge
EasyWrite three generic functions for any type whose values can be compared, with the bound Comparable. clamp(value, min, max) returns the value limited to the range. isSorted(items) returns whether every element is less than or equal to the next. median(items) returns the middle element of the sorted list (the lower of the two middle ones for an even size), or null for an empty list.
The supplied code reads a line of numbers and a line of words. It prints the numbers clamped to 0-10, whether each list is sorted, their medians and the first word clamped between b and m.
Your code goes in Ranges.kt. Main.kt holds the supplied input/output code and cannot be edited.
Try it yourself
fun main() {
// Supplied input/output code: keep it as it is
val input = generateSequence(::readLine).toList()
val numbers = input[0].split(" ").map { it.toInt() }
val words = input[1].split(" ")
println("clamped: " + numbers.map { clamp(it, 0, 10) })
println("numbers sorted: ${isSorted(numbers)}, median: ${median(numbers)}")
println("words sorted: ${isSorted(words)}, median: ${median(words)}")
println("word clamp: ${clamp(words[0], "b", "m")}")
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Classes and Objects
Working With FilesDefining ClassesPrimary Constructorsinit Blocks and ValidationSecondary ConstructorsRecap - Library Card4Inheritance
Open Classes and SubclassesOverriding Memberssuper and ConstructorsAbstract ClassesRecap - Staff Directory2Properties and Encapsulation
Custom AccessorsVisibility ModifiersPrivate Setterslazy and lateinitRecap - Bank Account5Interfaces
Declaring InterfacesDefault MethodsMultiple InterfacesInterfaces as TypesRecap - Payment Methods8Generics
Generic FunctionsGeneric ClassesType ConstraintsVariance With in and outRecap - Priority Queue11Project: Library Management
Books and MembersBorrowing BooksPractice on your own: Kotlin playground