Generics
Generics
What are Generics?
Generics allow you to write type-safe, reusable code that works with different data types without sacrificing type safety. Instead of writing separate classes for each type, you write one class with a type parameter.
Generic Functions
fun <T : Any> printItem(item: T) {
println("Item: $item (${item::class.simpleName})")
}
fun main() {
printItem(42)
printItem("Hello")
printItem(3.14)
printItem(true)
}
Generic Function with Return Type
fun <T> identity(value: T): T = value
fun main() {
val name: String = identity("Kotlin")
val num: Int = identity(100)
println(name) // Kotlin
println(num) // 100
}
Generic Classes
class Box<T : Any>(val value: T) {
fun getValue(): T = value
fun describe() = println("Box contains: $value (${value::class.simpleName})")
}
fun main() {
val intBox = Box(42)
val strBox = Box("Hello")
val listBox = Box(listOf(1, 2, 3))
intBox.describe() // Box contains: 42 (Int)
strBox.describe() // Box contains: Hello (String)
listBox.describe() // Box contains: [1, 2, 3] (ArrayList)
}
Generic Interfaces
interface Repository<T> {
fun findById(id: Int): T?
fun save(item: T)
fun getAll(): List<T>
}
data class User(val id: Int, val name: String)
class UserRepository : Repository<User> {
private val users = mutableListOf<User>()
override fun findById(id: Int) = users.find { it.id == id }
override fun save(item: User) { users.add(item) }
override fun getAll() = users.toList()
}
fun main() {
val repo = UserRepository()
repo.save(User(1, "Alice"))
repo.save(User(2, "Bob"))
println(repo.findById(1)) // User(id=1, name=Alice)
println(repo.getAll())
}
Type Constraints (Upper Bounds)
Restrict what types can be used as a type argument:
fun <T : Number> sum(a: T, b: T): Double {
return a.toDouble() + b.toDouble()
}
fun main() {
println(sum(3, 4)) // 7.0
println(sum(1.5, 2.5)) // 4.0
// sum("a", "b") // ERROR: String is not a Number
}
Multiple Constraints with where
fun <T> printIfComparable(a: T, b: T)
where T : Comparable<T>, T : Any {
if (a > b) println("$a > $b") else println("$a <= $b")
}
fun main() {
printIfComparable(5, 3) // 5 > 3
printIfComparable("abc", "xyz") // abc <= xyz
}