1. Antes de comenzar
Como ya te esforzaste por aprender los conceptos básicos de la programación en Kotlin, es hora de poner en práctica lo que aprendiste.
Estos ejercicios ponen a prueba tus conocimientos sobre los conceptos que estudiaste. Se basan en casos de uso reales, algunos de los cuales probablemente encontraste antes como usuario.
Sigue las instrucciones para encontrar una solución para cada ejercicio en el Playground de Kotlin. Si en alguna parte ya no sabes qué hacer, algunos de los ejercicios tienen pistas que pueden ayudarte. El código de solución de cada ejercicio está disponible al final, pero te recomendamos que lo resuelvas antes de verificar tus respuestas.
Realiza los ejercicios a un ritmo que te resulte cómodo. Hay estimaciones de duración para los ejercicios, pero no tienes que respetarlas. Tómate el tiempo necesario para resolver cada problema cuidadosamente. Las soluciones son solo una forma de resolver los ejercicios, por lo que puedes experimentar de la forma que desees.
Requisitos previos
- Estar familiarizado con el Playground de Kotlin
- Ser capaz de definir funciones y llamarlas
- Tener conocimientos de los conceptos básicos de programación de Kotlin, incluidas las variables y las funciones
println()
ymain()
- Tener conocimientos de condicionales de Kotlin, incluidas las sentencias y expresiones
if/else
ywhen
- Conocimientos de expresiones lambda de Kotlin
- Conocimiento sobre cómo manejar variables anulables
- Conocimiento sobre cómo crear clases y objetos de Kotlin
- Completar los condicionales de escritura en Kotlin, usar la nulabilidad, usar clases y objetos en Kotlin y usar tipos de funciones y expresiones lambda en codelabs de Kotlin
Qué necesitarás
- Playground de Kotlin
2. Notificaciones móviles
Por lo general, el teléfono te proporciona un resumen de las notificaciones.
En el código inicial que se proporciona en el siguiente fragmento de código, escribe un programa que imprima el mensaje de resumen según la cantidad de notificaciones que recibiste. El mensaje debe incluir lo siguiente:
- La cantidad exacta de notificaciones cuando haya menos de 100
99+
como cantidad de notificaciones cuando haya 100 o más
fun main() {
val morningNotification = 51
val eveningNotification = 135
printNotificationSummary(morningNotification)
printNotificationSummary(eveningNotification)
}
fun printNotificationSummary(numberOfMessages: Int) {
// Fill in the code.
}
Completa la función printNotificationSummary()
para que el programa imprima estas líneas:
You have 51 notifications. Your phone is blowing up! You have 99+ notifications.
3. Precio de las entradas de cine
Las entradas de cine suelen tener un precio diferente según la edad de los espectadores.
En el código inicial que se proporciona en el siguiente fragmento de código, escribe un programa que calcule los precios de estas entradas basados en la edad:
- Un precio de entrada infantil de USD 15 para personas de 12 años o menos.
- Un precio de entrada estándar de USD 30 para personas de entre 13 y 60 años. Los lunes, un precio estándar con descuento de USD 25 para el mismo grupo etario
- Un precio para adultos mayores de USD 20 para personas de 61 años o más (asumimos que la edad máxima de un espectador es de 100 años)
- Un valor de
-1
para indicar que el precio no es válido cuando un usuario ingresa una edad fuera de las especificaciones
fun main() {
val child = 5
val adult = 28
val senior = 87
val isMonday = true
println("The movie ticket price for a person aged $child is \$${ticketPrice(child, isMonday)}.")
println("The movie ticket price for a person aged $adult is \$${ticketPrice(adult, isMonday)}.")
println("The movie ticket price for a person aged $senior is \$${ticketPrice(senior, isMonday)}.")
}
fun ticketPrice(age: Int, isMonday: Boolean): Int {
// Fill in the code.
}
Completa la función ticketPrice()
para que el programa imprima estas líneas:
The movie ticket price for a person aged 5 is $15. The movie ticket price for a person aged 28 is $25. The movie ticket price for a person aged 87 is $20.
4. Conversor de temperatura
En el mundo, se usan tres escalas de temperatura principales: Celsius, Fahrenheit y Kelvin.
En el código inicial que se proporciona en el siguiente fragmento de código, escribe un programa que convierta una temperatura de una escala a otra con estas fórmulas:
- De grados Celsius a Fahrenheit: °F = 9/5 (°C) + 32
- Kelvin a Celsius: °C = K - 273.15
- De Fahrenheit a Kelvin: K = 5/9 (°F - 32) + 273.15
Ten en cuenta que el método String.format("%.2f", /* measurement */ )
se usa para convertir un número en un tipo String
con 2 decimales.
fun main() {
// Fill in the code.
}
fun printFinalTemperature(
initialMeasurement: Double,
initialUnit: String,
finalUnit: String,
conversionFormula: (Double) -> Double
) {
val finalMeasurement = String.format("%.2f", conversionFormula(initialMeasurement)) // two decimal places
println("$initialMeasurement degrees $initialUnit is $finalMeasurement degrees $finalUnit.")
}
Completa la función main()
para que llame a la función printFinalTemperature()
e imprima las siguientes líneas. Debes pasar argumentos para la fórmula de conversión y temperatura. Sugerencia: Te recomendamos usar valores Double
para evitar el truncamiento de Integer
durante las operaciones de división.
27.0 degrees Celsius is 80.60 degrees Fahrenheit. 350.0 degrees Kelvin is 76.85 degrees Celsius. 10.0 degrees Fahrenheit is 260.93 degrees Kelvin.
5. Catálogo de canciones
Imagina que necesitas crear una app de reproducción de música.
Crea una clase que pueda representar la estructura de una canción. La clase Song
debe incluir estos elementos de código:
- Propiedades para el título, el artista, el año de publicación y el recuento de reproducciones
- Propiedad que indica si la canción es popular (si el recuento de reproducciones es inferior a 1,000, considera que es poco popular)
- Un método para imprimir la descripción de una canción en este formato:
"[Título], interpretada por [artista], se lanzó en [año de lanzamiento]".
6. Perfil de Internet
A menudo, debes completar los perfiles de sitios web en línea que contienen campos obligatorios y no obligatorios. Por ejemplo, puedes agregar tu información personal y un vínculo a otras personas que te refirieron para que registraras tu perfil.
En el código inicial que se proporciona en el siguiente fragmento de código, escribe un programa que imprima los detalles del perfil de una persona.
fun main() {
val amanda = Person("Amanda", 33, "play tennis", null)
val atiqah = Person("Atiqah", 28, "climb", amanda)
amanda.showProfile()
atiqah.showProfile()
}
class Person(val name: String, val age: Int, val hobby: String?, val referrer: Person?) {
fun showProfile() {
// Fill in code
}
}
Completa la función showProfile()
para que el programa imprima estas líneas:
Name: Amanda Age: 33 Likes to play tennis. Doesn't have a referrer. Name: Atiqah Age: 28 Likes to climb. Has a referrer named Amanda, who likes to play tennis.
7. Teléfonos plegables
Por lo general, la pantalla del teléfono se enciende y se apaga cuando se presiona el botón de encendido. En cambio, si un teléfono plegable está plegado, su pantalla interna principal no se enciende cuando se presiona el botón de encendido.
En el código inicial que se proporciona en el siguiente fragmento de código, escribe una clase FoldablePhone
que se herede de la clase Phone
. Debe contener lo siguiente:
- Una propiedad que indique si el teléfono está plegado
- Un comportamiento de función
switchOn()
diferente del de la clasePhone
para que solo encienda la pantalla cuando el teléfono no esté plegado - Métodos para cambiar el estado de plegado
class Phone(var isScreenLightOn: Boolean = false){
fun switchOn() {
isScreenLightOn = true
}
fun switchOff() {
isScreenLightOn = false
}
fun checkPhoneScreenLight() {
val phoneScreenLight = if (isScreenLightOn) "on" else "off"
println("The phone screen's light is $phoneScreenLight.")
}
}
8. Subasta especial
Por lo general, en una subasta, el ofertante que ofrece el importe más alto determina el precio de un artículo. En esta subasta especial, si nadie oferta por un artículo, este se vende automáticamente a la casa de subastas al precio mínimo.
En el código inicial que se proporciona en el siguiente fragmento de código, se te proporciona una función auctionPrice()
que acepta un tipo Bid?
anulable como argumento:
fun main() {
val winningBid = Bid(5000, "Private Collector")
println("Item A is sold at ${auctionPrice(winningBid, 2000)}.")
println("Item B is sold at ${auctionPrice(null, 3000)}.")
}
class Bid(val amount: Int, val bidder: String)
fun auctionPrice(bid: Bid?, minimumPrice: Int): Int {
// Fill in the code.
}
Completa la función auctionPrice()
para que el programa imprima estas líneas:
Item A is sold at 5000. Item B is sold at 3000.
9. Código de solución
Notificaciones móviles
La solución usa una sentencia if/else
para imprimir el mensaje de resumen de notificaciones adecuado según la cantidad de mensajes de notificación recibidos:
fun main() {
val morningNotification = 51
val eveningNotification = 135
printNotificationSummary(morningNotification)
printNotificationSummary(eveningNotification)
}
fun printNotificationSummary(numberOfMessages: Int) {
if (numberOfMessages < 100) {
println("You have ${numberOfMessages} notifications.")
} else {
println("Your phone is blowing up! You have 99+ notifications.")
}
}
Precio de las entradas de cine
La solución usa una expresión when
para mostrar el precio de entrada apropiado según la edad del espectador. También usa una expresión if/else
simple para una de las ramas de la expresión when
a fin de agregar la condición adicional al precio estándar de la entrada.
El precio de la entrada en la rama else
muestra un valor -1
, que indica que el precio establecido no es válido para la rama else
. Una mejor implementación es que la rama else
arroje una excepción. Aprenderás sobre el manejo de excepciones en unidades futuras.
fun main() {
val child = 5
val adult = 28
val senior = 87
val isMonday = true
println("The movie ticket price for a person aged $child is \$${ticketPrice(child, isMonday)}.")
println("The movie ticket price for a person aged $adult is \$${ticketPrice(adult, isMonday)}.")
println("The movie ticket price for a person aged $senior is \$${ticketPrice(senior, isMonday)}.")
}
fun ticketPrice(age: Int, isMonday: Boolean): Int {
return when(age) {
in 0..12 -> 15
in 13..60 -> if (isMonday) 25 else 30
in 61..100 -> 20
else -> -1
}
}
Conversor de temperatura
La solución requiere que pases una función como parámetro a la función printFinalTemperature()
. La solución más breve pasa expresiones lambda como argumentos, usa la referencia del parámetro it
en lugar de los nombres de los parámetros y usa la sintaxis lambda final.
fun main() {
printFinalTemperature(27.0, "Celsius", "Fahrenheit") { 9.0 / 5.0 * it + 32 }
printFinalTemperature(350.0, "Kelvin", "Celsius") { it - 273.15 }
printFinalTemperature(10.0, "Fahrenheit", "Kelvin") { 5.0 / 9.0 * (it - 32) + 273.15 }
}
fun printFinalTemperature(
initialMeasurement: Double,
initialUnit: String,
finalUnit: String,
conversionFormula: (Double) -> Double
) {
val finalMeasurement = String.format("%.2f", conversionFormula(initialMeasurement)) // two decimal places
println("$initialMeasurement degrees $initialUnit is $finalMeasurement degrees $finalUnit.")
}
Catálogo de canciones
La solución contiene una clase Song
con un constructor predeterminado que acepta todos los parámetros obligatorios. La clase Song
también tiene una propiedad isPopular
que usa una función de método get personalizado y un método que imprime su propia descripción. Puedes crear una instancia de la clase en la función main()
y llamar a sus métodos para probar si la implementación es correcta. Puedes usar guiones bajos cuando escribas números grandes, como el valor 1_000_000
, para que sea más legible.
fun main() {
val brunoSong = Song("We Don't Talk About Bruno", "Encanto Cast", 2022, 1_000_000)
brunoSong.printDescription()
println(brunoSong.isPopular)
}
class Song(
val title: String,
val artist: String,
val yearPublished: Int,
val playCount: Int
){
val isPopular: Boolean
get() = playCount >= 1000
fun printDescription() {
println("$title, performed by $artist, was released in $yearPublished.")
}
}
Cuando llamas a la función println()
en los métodos de la instancia, es posible que el programa imprima este resultado:
We Don't Talk About Bruno, performed by Encanto Cast, was released in 2022. true
Perfil de Internet
La solución contiene verificaciones nulas en diferentes declaraciones if/else
para imprimir un texto distinto en función de si varias propiedades de clase son null
:
fun main() {
val amanda = Person("Amanda", 33, "play tennis", null)
val atiqah = Person("Atiqah", 28, "climb", amanda)
amanda.showProfile()
atiqah.showProfile()
}
class Person(val name: String, val age: Int, val hobby: String?, val referrer: Person?) {
fun showProfile() {
println("Name: $name")
println("Age: $age")
if(hobby != null) {
print("Likes to $hobby. ")
}
if(referrer != null) {
print("Has a referrer named ${referrer.name}")
if(referrer.hobby != null) {
print(", who likes to ${referrer.hobby}.")
} else {
print(".")
}
} else {
print("Doesn't have a referrer.")
}
print("\n\n")
}
}
Teléfonos plegables
Para que la clase Phone
sea una superior, debes agregar la palabra clave open
antes del nombre de la clase para que se abra. Para anular el método switchOn()
en la clase FoldablePhone
, debes hacer que el método de la clase Phone
se abra. Para ello, agrega la palabra clave open
antes del método.
La solución contiene una clase FoldablePhone
con un constructor predeterminado que incluye un argumento predeterminado para el parámetro isFolded
. La clase FoldablePhone
también tiene dos métodos para cambiar la propiedad isFolded
a un valor true
o false
. Además, anula el método switchOn()
heredado de la clase Phone
.
Puedes crear una instancia de la clase en la función main()
y llamar a sus métodos para probar si la implementación es correcta.
open class Phone(var isScreenLightOn: Boolean = false){
open fun switchOn() {
isScreenLightOn = true
}
fun switchOff() {
isScreenLightOn = false
}
fun checkPhoneScreenLight() {
val phoneScreenLight = if (isScreenLightOn) "on" else "off"
println("The phone screen's light is $phoneScreenLight.")
}
}
class FoldablePhone(var isFolded: Boolean = true): Phone() {
override fun switchOn() {
if (!isFolded) {
isScreenLightOn = true
}
}
fun fold() {
isFolded = true
}
fun unfold() {
isFolded = false
}
}
fun main() {
val newFoldablePhone = FoldablePhone()
newFoldablePhone.switchOn()
newFoldablePhone.checkPhoneScreenLight()
newFoldablePhone.unfold()
newFoldablePhone.switchOn()
newFoldablePhone.checkPhoneScreenLight()
}
Este es el resultado:
The phone screen's light is off. The phone screen's light is on.
Subasta especial
La solución usa el operador de llamada segura ?.
y el operador Elvis ?:
para mostrar el precio correcto:
fun main() {
val winningBid = Bid(5000, "Private Collector")
println("Item A is sold at ${auctionPrice(winningBid, 2000)}.")
println("Item B is sold at ${auctionPrice(null, 3000)}.")
}
class Bid(val amount: Int, val bidder: String)
fun auctionPrice(bid: Bid?, minimumPrice: Int): Int {
return bid?.amount ?: minimumPrice
}
10. Práctica adicional
Si deseas obtener más información sobre el lenguaje Kotlin, consulta la segmentación básica de Kotlin en JetBrains Academy. Para ir a un tema específico, ve al mapa del conocimiento a fin de ver la lista de temas del segmento.