Funciones genéricas y restricciones de tipos con where
Escriba funciones genéricas con una o varias restricciones de tipos.
Funciones genéricas y restricciones de tipos con where es una lección gratuita de Kotlin Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Kotlin Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Kotlin Academy incluye 4 lecciones en total.
Conceptos básicos de las funciones genéricas
Las funciones genéricas usan parámetros de tipo entre corchetes angulares antes del nombre de la función. El parámetro de tipo puede utilizarse en los tipos de los parámetros y en los tipos de retorno.
fun <T> identity(value: T): T = value
fun <T> listOf2(a: T, b: T): List<T> = listOf(a, b)
fun main() {
println(identity(42)) // 42
println(identity("hello")) // hello
println(listOf2(1, 2)) // [1, 2]
}Límites superiores con la restricción :
Restrinja un parámetro de tipo con un límite superior mediante :. El tipo debe ser un subtipo del límite.
fun <T : Comparable<T>> max(a: T, b: T): T = if (a >= b) a else b
fun main() {
println(max(3, 7)) // 7
println(max("apple", "banana")) // banana
// max(listOf(1), listOf(2)) // error: List is not Comparable
}Límite superior anulable
El límite superior predeterminado es Any? (anulable). Use T : Any para excluir los valores nulos.
fun <T : Any> notNull(value: T?): T {
return value ?: throw IllegalArgumentException("Value is null")
}
fun main() {
println(notNull("hello")) // hello
try { notNull(null) } catch (e: Exception) { println(e.message) }
}Varias restricciones con where
Use la cláusula where para aplicar varias restricciones a un solo parámetro de tipo.
fun <T> process(item: T): String
where T : Comparable<T>, T : CharSequence {
return "Length=${item.length}, sorted=${item > "a"}"
}
fun main() {
println(process("kotlin")) // Length=6, sorted=true
// process(42) // error: Int doesn't implement CharSequence
}where en una clase
La cláusula where también funciona con parámetros de tipo de nivel de clase.
class SortedContainer<T>(private val items: MutableList<T> = mutableListOf())
where T : Comparable<T>, T : Any {
fun add(item: T) { items.add(item); items.sort() }
fun top(): T? = items.lastOrNull()
}
fun main() {
val c = SortedContainer<Int>()
c.add(5); c.add(2); c.add(8)
println(c.top()) // 8
}Funciones de extensión genéricas
Las funciones de extensión también pueden tener parámetros de tipo, lo que permite disponer de ellas en tipos genéricos específicos.
fun <T : Comparable<T>> List<T>.second(): T? {
return if (size >= 2) this[1] else null
}
fun main() {
println(listOf(10, 20, 30).second()) // 20
println(listOf("a").second()) // null
}Parámetro de tipo en la posición de retorno
Las funciones genéricas pueden inferir el tipo a partir del contexto, evitando especificar argumentos de tipo explícitos en el sitio de llamada.
fun <T> MutableList<T>.popOrDefault(default: T): T {
return if (isEmpty()) default else removeAt(lastIndex)
}
fun main() {
val list = mutableListOf(1, 2, 3)
println(list.popOrDefault(0)) // 3
println(list.popOrDefault(0)) // 2
println(mutableListOf<Int>().popOrDefault(-1)) // -1
}Utilidades genéricas reutilizables
Las funciones genéricas permiten reutilizar funciones auxiliares con distintos tipos sin duplicar código.
fun <T> Iterable<T>.firstOrElse(default: T): T = firstOrNull() ?: default
fun <T, R : Comparable<R>> Iterable<T>.maxByOrElse(selector: (T) -> R, default: T): T =
maxByOrNull(selector) ?: default
fun main() {
println(listOf<String>().firstOrElse("fallback")) // fallback
println(listOf("a","bbb","cc").maxByOrElse({ it.length }, "")) // bbb
}Proyección de estrella frente a comodín acotado
Compare el uso de un parámetro de tipo acotado (útil cuando necesita producir o consumir T) con la proyección de estrella (cuando se desconoce el tipo).
fun <T : Number> sumList(list: List<T>): Double =
list.sumOf { it.toDouble() }
// Star projection: read-only, type unknown
fun printAll(list: List<*>) = list.forEach { println(it) }
fun main() {
println(sumList(listOf(1, 2, 3))) // 6.0
printAll(listOf("a", 1, true)) // a, 1, true
}Intercambio genérico de un Pair
Una función genérica sencilla pero ilustrativa que invierte los componentes de un Pair.
fun <A, B> Pair<A, B>.swap(): Pair<B, A> = Pair(second, first)
fun main() {
val pair = Pair("hello", 42)
val swapped = pair.swap()
println(swapped) // (42, hello)
}Práctica: desenvoltorio genérico de Result
Use genéricos acotados para escribir una utilidad que aplique una transformación con tipos sobre un Result<T>.
fun <T : Any, R : Any> Result<T>.mapNotNull(transform: (T) -> R?): Result<R> {
return fold(
onSuccess = { v ->
val r = transform(v)
if (r != null) Result.success(r) else Result.failure(NoSuchElementException())
},
onFailure = { Result.failure(it) }
)
}
fun main() {
val r = Result.success("123")
val n = r.mapNotNull { it.toIntOrNull() }
println(n) // Success(123)
}Comprobación rápida
¿Cómo se aplican varias restricciones a un parámetro de tipo?
Resumen
Las funciones genéricas utilizan parámetros de tipo para escribir código reutilizable y seguro con respecto a los tipos. Use : para un único límite o where para varios límites. El compilador de Kotlin aplica las restricciones en el sitio de llamada.
Preguntas frecuentes
¿La lección «Funciones genéricas y restricciones de tipos con where» es gratis?
Sí — el texto completo de «Funciones genéricas y restricciones de tipos con where» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Kotlin Academy, actualiza a CoddyKit PRO. El curso de Kotlin Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Funciones genéricas y restricciones de tipos con where»?
Escriba funciones genéricas con una o varias restricciones de tipos. Practicas Kotlin Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Kotlin Academy?
No se requiere experiencia previa. Kotlin Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.
¿Cuánto tiempo toma la lección «Funciones genéricas y restricciones de tipos con where»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Kotlin Academy?
Sí. Cada lección de Kotlin Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Funciones genéricas y restricciones de tipos con where
- Varianza en el sitio de declaración: in y out
- Proyección estrella y cuándo usar *
- Borrado de tipos y parámetros de tipo reified