📖 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
Step 1: Understand the upper bound syntax
The syntax <T : Number> means T is limited to types that inherit from Number.
Step 2: Interpret subtype relationship
This means T can be Number or any subclass like Int or Double, but not unrelated types.
Final Answer:
T must be a subtype of the Number class -> Option A
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
Step 1: Recall Kotlin's upper bound syntax
Kotlin uses <T : Interface> to specify T must implement that interface.
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.
Final Answer:
fun <T : Comparable<T>> max(a: T, b: T): T { ... } -> Option B
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
Step 1: Understand the generic constraint
The function requires T to be a subtype of Number, so Int and Double are valid.
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.
Final Answer:
10.0 and 7.0 -> Option D
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
Step 1: Check Comparable usage
Comparable is a generic interface and requires a type parameter, so it should be Comparable<T>.
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.
Final Answer:
Missing generic type parameter in Comparable -> Option C
Quick Check:
Comparable must be parameterized as Comparable<T> [OK]
Hint: Always specify type parameter for Comparable like Comparable<T> [OK]
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
Step 1: Analyze the function's type constraint
The function requires a List of elements where each element is a subtype of Number.
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.
Final Answer:
sumList(listOf("1", "2", "3")) -> Option A
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 unknownstrongwhile earning +1 Grip toward your certificate.