Kotlin: ¿en el blanco o fuera de lugar?
\nKotlin no es solo "Java sin código repetitivo". Es un lenguaje que conquistó el corazón de Google, superó a Swift en ritmo de crecimiento y se convirtió en un requisito obligatorio en las ofertas de trabajo para desarrolladores móviles. Pero he aquí la paradoja: muchos llegan a la entrevista pensando "sé Java, lo resolveré" y se van con los ojos rojos. Porque Kotlin es otro mundo: sin null, con corrutinas y funciones de extensión que rompen los esquemas.
\nEn PythonLib (sí, somos de Python, pero Kotlin es imprescindible para el backend moderno y las aplicaciones móviles) hemos recopilado un caso real: cómo superar una entrevista de Kotlin con brillantez. Sin rodeos: solo código, lógica y trucos secretos que no se enseñan en los cursos.
\n\n1. ¿Por qué Kotlin no es "simplemente Java 2.0"?
\nLa primera pregunta que te harán: "¿Cuál es la diferencia fundamental entre Kotlin y Java?". Si dices "la sintaxis es más corta", te pedirán amablemente que salgas. La diferencia principal es la null safety a nivel de tipos. En Java puedes olvidarte de comprobar si un objeto es null y obtener un NPE en tiempo de ejecución. En Kotlin, el compilador ni siquiera te dejará compilar el código si hay riesgo de null.
\n// Java\nString name = null;\nint length = name.length(); // NPE en tiempo de ejecución\n\n// Kotlin\nvar name: String? = null\nval length = name?.length ?: 0 // Seguro: length = 0\nPero esto es lo básico. El entrevistador profundizará: preguntará sobre !! (aserción no nula), el operador Elvis ?: y las llamadas seguras ?.. Tu tarea es demostrar que entiendes: !! es malo, y ?: es tu amigo.
- \n
- Safe call (?.) — si el objeto es null, devuelve null. \n
- Elvis (?:) — si lo de la izquierda es null, toma el valor de la derecha. \n
- !! — úsalo solo si estás 100% seguro, de lo contrario, es un error. \n
2. Extension functions: magia que hay que explicar
\nPregunta: "¿Cómo agregar un método a una clase que no puedes modificar?". En Java: patrón Decorator o clase Util. En Kotlin: extension functions. No es un cambio real en la clase, sino azúcar sintáctico que hace el código legible.
\n// Extension function para String\nfun String.isEmail(): Boolean {\n return this.contains("@") && this.contains(".")\n}\n\n// Uso\nval email = "user@pythonlib.ru"\nprintln(email.isEmail()) // true\nEl entrevistador puede preguntar: "¿Se puede sobrescribir una extension function?". Respuesta: no, es una llamada estática, no dinámica. Si declaras una función con el mismo nombre en la clase, el método de la clase tiene prioridad.
\n\n3. Sealed class vs Enum: ¿cuándo usar cada uno?
\nEsta es una pregunta clásica de nivel medio. Enum: para un conjunto fijo de constantes (días de la semana, estados). Sealed class: para una jerarquía limitada de tipos, donde cada elemento puede tener su propio estado.
\nsealed class Result {\n data class Success(val data: String) : Result()\n data class Error(val code: Int, val message: String) : Result()\n object Loading : Result()\n}\n\nfun handleResult(result: Result) {\n when (result) {\n is Result.Success -> println("Data: ${result.data}")\n is Result.Error -> println("Error ${result.code}: ${result.message}")\n Result.Loading -> println("Loading...")\n }\n}\n¿Por qué es importante? Porque when con sealed class garantiza que has manejado todos los casos. El compilador no te dejará olvidar un nuevo tipo si lo agregas a la sealed class.
4. Corrutinas: cómo no fracasar en la asincronía
\nEl tema donde fallan el 70% de los candidatos. Las corrutinas no son hilos. Son "hilos" ligeros que pueden suspenderse sin bloquear el hilo.
\nsuspend fun fetchData(): String {\n delay(1000) // ¡No bloquea el hilo!\n return "Data from PythonLib"\n}\n\nfun main() = runBlocking {\n launch {\n val result = fetchData()\n