Bird
Raised Fist0
Kotlinprogramming~5 mins

Type constraints with upper bounds in Kotlin

Choose your learning style10 modes available
Introduction
Type constraints with upper bounds help you tell the program to only accept certain types that share common features. This keeps your code safe and clear.
When you want a function to work only with types that have a specific property or behavior.
When you write a class that should only handle objects that follow a certain rule.
When you want to reuse code but limit it to types that can do certain actions.
When you want to avoid errors by restricting types to those that support needed operations.
Syntax
Kotlin
fun <T : SomeType> functionName(param: T) { 
    // code using param
}
The means T must be SomeType or a subtype of it.
You can use multiple constraints with where clause if needed.
Examples
This function accepts any type that is a Number or inherits from Number.
Kotlin
fun <T : Number> printDouble(value: T) {
    println(value.toDouble() * 2)
}
Here, T must be a non-null type (Any is the root of all non-null types).
Kotlin
fun <T> copyItems(source: List<T>, destination: MutableList<T>) where T : Any {
    for (item in source) {
        destination.add(item)
    }
}
This class only accepts types that can be compared with themselves.
Kotlin
class Box<T : Comparable<T>>(val value: T) {
    fun isGreaterThan(other: T): Boolean {
        return value > other
    }
}
Sample Program
This program defines a function that returns the bigger of two values. It only works with types that can be compared, like numbers or strings.
Kotlin
fun <T : Comparable<T>> maxOfTwo(a: T, b: T): T {
    return if (a > b) a else b
}

fun main() {
    println(maxOfTwo(5, 10))
    println(maxOfTwo("apple", "banana"))
}
OutputSuccess
Important Notes
Upper bounds ensure your generic types have the features you need.
You can use multiple upper bounds with syntax like where T : A, T : B.
If you don't specify an upper bound, Kotlin uses 'Any?' by default, which allows any type including null.
Summary
Type constraints with upper bounds limit generic types to certain classes or interfaces.
They help make your code safer by ensuring needed functions or properties exist.
Use the syntax to set an upper bound on T.

Practice

(1/5)
1. What does the syntax <T : Number> mean in Kotlin generics?
easy
A. T must be a subtype of the Number class
B. T can be any type including Number
C. T must be a supertype of Number
D. T must be exactly the Number class

Solution

  1. Step 1: Understand the upper bound syntax

    The syntax <T : Number> means T is limited to types that inherit from Number.
  2. Step 2: Interpret subtype relationship

    This means T can be Number or any subclass like Int or Double, but not unrelated types.
  3. Final Answer:

    T must be a subtype of the Number class -> Option A
  4. Quick Check:

    Upper bound <T : Number> = subtype limit [OK]
Hint: Look for ': Type' to mean 'subtype of Type' [OK]
Common Mistakes:
  • Thinking T can be any type
  • Confusing subtype with supertype
  • Assuming exact type match only
2. Which of the following is the correct syntax to declare a generic function with an upper bound on type T to implement the Comparable interface?
easy
A. fun <T> max(a: T, b: T): T where T implements Comparable<T> { ... }
B. fun max(a: T, b: T): T { ... }
C. fun max(a: T, b: T): T { ... }
D. fun max(a: T, b: T): T { ... }

Solution

  1. Step 1: Recall Kotlin's upper bound syntax

    Kotlin uses <T : Interface> to specify T must implement that interface.
  2. Step 2: Identify correct syntax for Comparable

    The correct syntax is fun <T : Comparable<T>> .... Options B and D use Java syntax, and A uses a where clause but with incorrect syntax.
  3. Final Answer:

    fun <T : Comparable<T>> max(a: T, b: T): T { ... } -> Option B
  4. Quick Check:

    Kotlin upper bound uses ':' not 'implements' or 'extends' [OK]
Hint: Use ':' for upper bounds, not 'implements' or 'extends' [OK]
Common Mistakes:
  • Using Java syntax keywords like 'implements' or 'extends'
  • Confusing where clause syntax
  • Missing generic type parameter declaration
3. What will be the output of this Kotlin code?
fun <T : Number> printDouble(value: T) {
    println(value.toDouble() * 2)
}

fun main() {
    printDouble(5)
    printDouble(3.5)
}
medium
A. 5 and 3.5
B. Runtime error due to toDouble() call
C. Compilation error due to type mismatch
D. 10.0 and 7.0

Solution

  1. Step 1: Understand the generic constraint

    The function requires T to be a subtype of Number, so Int and Double are valid.
  2. Step 2: Calculate the output

    For 5 (Int), toDouble() is 5.0, multiplied by 2 is 10.0.
    For 3.5 (Double), toDouble() is 3.5, multiplied by 2 is 7.0.
  3. Final Answer:

    10.0 and 7.0 -> Option D
  4. Quick Check:

    Number constraint allows toDouble(), output matches calculations [OK]
Hint: Remember Number types have toDouble() method [OK]
Common Mistakes:
  • Expecting compilation error for Int argument
  • Confusing printed values with input values
  • Thinking toDouble() causes runtime error
4. Identify the error in this Kotlin code snippet:
fun <T : Comparable> compareValues(a: T, b: T): T {
    return if (a > b) a else b
}
medium
A. No error, code is correct
B. Cannot use '>' operator with Comparable
C. Missing generic type parameter in Comparable
D. Function must return Boolean, not T

Solution

  1. Step 1: Check Comparable usage

    Comparable is a generic interface and requires a type parameter, so it should be Comparable<T>.
  2. Step 2: Understand operator usage

    The '>' operator is not directly supported for Comparable, but Kotlin allows it if Comparable<T> is specified and operator overloading is present.
  3. Final Answer:

    Missing generic type parameter in Comparable -> Option C
  4. Quick Check:

    Comparable must be parameterized as Comparable<T> [OK]
Hint: Always specify type parameter for Comparable like Comparable<T> [OK]
Common Mistakes:
  • Omitting generic parameter in Comparable
  • Assuming '>' works without Comparable<T>
  • Confusing return type requirements
5. Given this Kotlin function:
fun <T : Number> sumList(numbers: List<T>): Double {
    return numbers.sumOf { it.toDouble() }
}

Which of these calls will cause a compilation error?
hard
A. sumList(listOf("1", "2", "3"))
B. sumList(listOf(1.5, 2.5, 3.5))
C. sumList(listOf(1, 2, 3))
D. sumList(listOf(1L, 2L, 3L))

Solution

  1. Step 1: Analyze the function's type constraint

    The function requires a List of elements where each element is a subtype of Number.
  2. Step 2: Check each call's argument type

    Options B, C, and D pass lists of Double, Int, and Long respectively.
    sumList(listOf("1", "2", "3")) passes a list of Strings, which are not subtypes of Number, causing a compilation error.
  3. Final Answer:

    sumList(listOf("1", "2", "3")) -> Option A
  4. Quick Check:

    Only Number subtypes allowed, String list fails [OK]
Hint: Only Number subtypes allowed in sumList argument [OK]
Common Mistakes:
  • Passing String list instead of Number list
  • Assuming any list works
  • Ignoring generic type constraints
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard