Bird
Raised Fist0
Kotlinprogramming~30 mins

Type constraints with upper bounds in Kotlin - Mini Project: Build & Apply

Choose your learning style10 modes available
Type Constraints with Upper Bounds in Kotlin
📖 Scenario: You are building a simple Kotlin program that works with shapes. Each shape can calculate its area. You want to write a function that accepts only shapes or their subclasses.
🎯 Goal: Create a generic function with a type constraint that accepts only objects of type Shape or its subclasses, and prints their area.
📋 What You'll Learn
Create an open class called Shape with an abstract function area() that returns a Double.
Create a subclass called Circle that inherits from Shape and implements area().
Create a generic function called printArea with a type parameter T constrained to Shape or its subclasses.
Inside printArea, call the area() function of the passed object and print the result.
💡 Why This Matters
🌍 Real World
Type constraints with upper bounds help ensure functions work only with compatible types, preventing errors and making code safer.
💼 Career
Understanding generics and type constraints is important for writing reusable and type-safe Kotlin code in professional Android or backend development.
Progress0 / 4 steps
1
Create the Shape class
Create an open class called Shape with an abstract function area() that returns a Double.
Kotlin
Hint

Use open abstract class Shape and define abstract fun area(): Double inside it.

2
Create the Circle subclass
Create a class called Circle that inherits from Shape. Add a property radius of type Double and override the area() function to return the area of the circle using 3.14 * radius * radius.
Kotlin
Hint

Use class Circle(val radius: Double) : Shape() and override area().

3
Create the generic function with upper bound
Create a generic function called printArea with a type parameter T that has an upper bound of Shape. The function should take a parameter shape of type T and print the area by calling shape.area().
Kotlin
Hint

Define fun <T : Shape> printArea(shape: T) and print the area.

4
Call the function and print the area
Create a Circle object with radius 5.0 and call printArea with this object. Print the output.
Kotlin
Hint

Create val circle = Circle(5.0) and call printArea(circle).

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