KotlinIntermedio14 oct 2025
Cuando tus extensiones se estrellan contra la realidad
snippet.kotlin
class PaymentGatewayResponse(val code: Int) {
fun getStatusMessage(): String {
return when (code) {
200 -> "Payment Approved"
400 -> "Bad Request"
else -> "Unknown Status"
}
}
}
fun PaymentGatewayResponse.getStatusMessage(): String {
return when (this.code) {
200 -> "Transaction Successful! 🎉"
400 -> "Client Error: Missing Data 🤦♀️"
else -> "Unrecognized Code 🤷♂️"
}
}
fun main() {
val successResponse = PaymentGatewayResponse(200)
val errorResponse = PaymentGatewayResponse(400)
println("Success: ${successResponse.getStatusMessage()}")
println("Error: ${errorResponse.getStatusMessage()}")
}¿Qué crees que imprime?
✅ Salida Esperada
Success: Transaction Successful! 🎉
Error: Client Error: Missing Data 🤦♀️⚠️ Salida Real
Success: Payment Approved
Error: Bad Request¿Por qué pasa esto?
¡Ay, las extensiones! Son como superpoderes que le das a clases que no son tuyas. Pero cuidado, si la clase ya tiene un método con la **misma firma**, tu extensión es como un chiste que nadie escucha. 🤫
Aquí, definimos una extensión `getStatusMessage()` para `PaymentGatewayResponse`. Esperaríamos que nuestro código mágico de emojis se ejecutara. Pero no. La clase `PaymentGatewayResponse` ya tiene un `getStatusMessage()` como **miembro de la clase**. Y en Kotlin, el **método miembro SIEMPRE tiene prioridad** sobre cualquier extensión con la misma firma. Es como si el método original tuviera un pase VIP y tu extensión se quedara fuera de la discoteca. 🕺➡️💃
Esto ocurre porque las extensiones **no son verdaderos miembros** de la clase; son funciones estáticas que se resuelven en tiempo de compilación según el tipo declarado del receptor. ¡No hay polimorfismo involucrado! Así que, si una librería actualiza una clase y añade un método con el mismo nombre que tu extensión, tu código de repente empezará a llamar al método de la librería, ¡silenciosamente cambiando el comportamiento!
Conceptos relacionados
extension-functionsmethod-resolutionshadowing