anexos:kotlin2
Diferencias
Muestra las diferencias entre dos versiones de la página.
| anexos:kotlin2 [2026/09/21 11:05] – creado fernando | anexos:kotlin2 [2026/09/21 13:14] (actual) – fernando | ||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| ====== Programación Orientada a Objetos en Kotlin ====== | ====== Programación Orientada a Objetos en Kotlin ====== | ||
| + | |||
| + | ===== Clases ===== | ||
| + | |||
| + | La **Programación Orientada a Objetos (POO)** es un paradigma de programación basado en la utilización de **objetos**. | ||
| + | |||
| + | Un objeto agrupa principalmente: | ||
| + | |||
| + | * **Datos**, representados mediante propiedades. | ||
| + | * **Comportamiento**, | ||
| + | |||
| + | Por ejemplo, si queremos representar un coche podríamos tener: | ||
| + | |||
| + | < | ||
| + | Coche | ||
| + | |||
| + | Propiedades: | ||
| + | marca | ||
| + | modelo | ||
| + | velocidad | ||
| + | |||
| + | Funciones: | ||
| + | acelerar() | ||
| + | frenar() | ||
| + | mostrarInformacion() </ | ||
| + | |||
| + | Para definir este tipo de objetos utilizaremos **clases**. | ||
| + | |||
| + | ==== Clases y objetos ==== | ||
| + | |||
| + | Una **clase** es una plantilla que define las características y el comportamiento que tendrán los objetos creados a partir de ella. | ||
| + | |||
| + | Por ejemplo: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Coche { | ||
| + | var marca = "" | ||
| + | var modelo = "" | ||
| + | var velocidad = 0 | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Esta clase define cómo serán los objetos de tipo `Coche`. | ||
| + | |||
| + | Sin embargo, declarar una clase **no crea ningún coche**. | ||
| + | |||
| + | Para trabajar con ella debemos crear objetos o **instancias** de la clase. | ||
| + | |||
| + | <WRAP info> | ||
| + | **Clase frente a objeto** | ||
| + | |||
| + | Podemos entender una clase como un plano o plantilla y un objeto como una realización concreta de ese plano. | ||
| + | |||
| + | Una misma clase puede utilizarse para crear muchos objetos diferentes. </ | ||
| + | |||
| + | ==== Declaración de una clase ==== | ||
| + | |||
| + | Para declarar una clase utilizamos la palabra reservada `class` seguida del nombre de la clase: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona { | ||
| + | |||
| + | } </ | ||
| + | |||
| + | Por convenio, los nombres de las clases comienzan con mayúscula: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona | ||
| + | class Alumno | ||
| + | class Producto | ||
| + | class CuentaBancaria | ||
| + | </ | ||
| + | |||
| + | Una clase puede estar formada por dos partes: | ||
| + | |||
| + | * **Cabecera de la clase**. | ||
| + | * **Cuerpo de la clase**. | ||
| + | |||
| + | Por ejemplo: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona(val nombre: String) { | ||
| + | |||
| + | ``` | ||
| + | var edad = 0 | ||
| + | |||
| + | fun saludar() { | ||
| + | println(" | ||
| + | } | ||
| + | ``` | ||
| + | |||
| + | } </ | ||
| + | |||
| + | La cabecera es: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona(val nombre: String) | ||
| + | </ | ||
| + | |||
| + | El cuerpo es todo lo que aparece entre `{ }`: | ||
| + | |||
| + | <code kotlin> | ||
| + | { | ||
| + | var edad = 0 | ||
| + | |||
| + | ``` | ||
| + | fun saludar() { | ||
| + | println(" | ||
| + | } | ||
| + | ``` | ||
| + | |||
| + | } </ | ||
| + | |||
| + | El cuerpo puede contener, entre otros elementos: | ||
| + | |||
| + | * Propiedades. | ||
| + | * Funciones. | ||
| + | * Bloques de inicialización. | ||
| + | * Constructores secundarios. | ||
| + | * Otras clases u objetos. | ||
| + | |||
| + | Si una clase no necesita cuerpo podemos omitir las llaves: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona(val nombre: String, var edad: Int) | ||
| + | </ | ||
| + | |||
| + | ==== Crear objetos ==== | ||
| + | |||
| + | Para crear un objeto escribimos el nombre de la clase seguido de paréntesis: | ||
| + | |||
| + | <code kotlin> | ||
| + | val persona = Persona(" | ||
| + | </ | ||
| + | |||
| + | A esta operación la denominamos **instanciar una clase**. | ||
| + | |||
| + | `persona` es ahora un objeto o instancia de `Persona`. | ||
| + | |||
| + | <WRAP important> | ||
| + | A diferencia de otros lenguajes orientados a objetos como Java, en Kotlin **no se utiliza la palabra `new`** para crear objetos. | ||
| + | </ | ||
| + | |||
| + | Por ejemplo: | ||
| + | |||
| + | <code kotlin> | ||
| + | // Kotlin | ||
| + | val persona = Persona(" | ||
| + | </ | ||
| + | |||
| + | No escribimos: | ||
| + | |||
| + | <code kotlin> | ||
| + | // Incorrecto en Kotlin | ||
| + | // val persona = new Persona(" | ||
| + | </ | ||
| + | |||
| + | Podemos crear múltiples objetos de una misma clase: | ||
| + | |||
| + | <code kotlin> | ||
| + | val persona1 = Persona(" | ||
| + | val persona2 = Persona(" | ||
| + | val persona3 = Persona(" | ||
| + | </ | ||
| + | |||
| + | Todos son objetos diferentes, aunque hayan sido creados utilizando la misma clase. | ||
| + | |||
| + | ==== Propiedades ==== | ||
| + | |||
| + | Las variables que forman parte de una clase reciben normalmente el nombre de **propiedades**. | ||
| + | |||
| + | Por ejemplo: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Coche { | ||
| + | var marca = "" | ||
| + | var modelo = "" | ||
| + | var velocidad = 0 | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | La clase `Coche` tiene tres propiedades: | ||
| + | |||
| + | < | ||
| + | marca | ||
| + | modelo | ||
| + | velocidad | ||
| + | </ | ||
| + | |||
| + | Podemos acceder a ellas utilizando el operador `.`: | ||
| + | |||
| + | <code kotlin> | ||
| + | val coche = Coche() | ||
| + | |||
| + | coche.marca = " | ||
| + | coche.modelo = " | ||
| + | coche.velocidad = 50 | ||
| + | |||
| + | println(coche.marca) | ||
| + | println(coche.modelo) | ||
| + | println(coche.velocidad) </ | ||
| + | |||
| + | ==== Propiedades val y var ==== | ||
| + | |||
| + | Al igual que las variables normales, las propiedades pueden declararse utilizando `val` o `var`. | ||
| + | |||
| + | Por ejemplo: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona( | ||
| + | val nombre: String, | ||
| + | var edad: Int | ||
| + | ) | ||
| + | </ | ||
| + | |||
| + | En este caso: | ||
| + | |||
| + | * `nombre` es una propiedad que no puede reasignarse. | ||
| + | * `edad` es una propiedad que puede modificarse. | ||
| + | |||
| + | <code kotlin> | ||
| + | val persona = Persona(" | ||
| + | |||
| + | persona.edad = 21 </ | ||
| + | |||
| + | Esto es correcto. | ||
| + | |||
| + | Sin embargo: | ||
| + | |||
| + | <code kotlin> | ||
| + | // ERROR | ||
| + | // persona.nombre = " | ||
| + | </ | ||
| + | |||
| + | no está permitido porque `nombre` fue declarado mediante `val`. | ||
| + | |||
| + | <WRAP tip> | ||
| + | Al igual que con las variables normales, es recomendable utilizar `val` cuando una propiedad no necesite ser reasignada. | ||
| + | </ | ||
| + | |||
| + | ==== Funciones de una clase ==== | ||
| + | |||
| + | Las clases también pueden contener funciones. | ||
| + | |||
| + | Estas funciones representan el **comportamiento de los objetos**. | ||
| + | |||
| + | Por ejemplo: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Coche( | ||
| + | val marca: String, | ||
| + | val modelo: String, | ||
| + | var velocidad: Int | ||
| + | ) { | ||
| + | |||
| + | ``` | ||
| + | fun acelerar() { | ||
| + | velocidad += 10 | ||
| + | } | ||
| + | |||
| + | fun frenar() { | ||
| + | velocidad -= 10 | ||
| + | } | ||
| + | |||
| + | fun mostrarInformacion() { | ||
| + | println(" | ||
| + | } | ||
| + | ``` | ||
| + | |||
| + | } </ | ||
| + | |||
| + | Podemos utilizar estas funciones mediante el operador `.`: | ||
| + | |||
| + | <code kotlin> | ||
| + | fun main() { | ||
| + | |||
| + | ``` | ||
| + | val coche = Coche( | ||
| + | " | ||
| + | " | ||
| + | 0 | ||
| + | ) | ||
| + | |||
| + | coche.acelerar() | ||
| + | coche.acelerar() | ||
| + | |||
| + | coche.mostrarInformacion() | ||
| + | ``` | ||
| + | |||
| + | } </ | ||
| + | |||
| + | Resultado: | ||
| + | |||
| + | < | ||
| + | Toyota Corolla - 20 km/h | ||
| + | </ | ||
| + | |||
| + | Las funciones pueden acceder directamente a las propiedades de su objeto: | ||
| + | |||
| + | <code kotlin> | ||
| + | fun acelerar() { | ||
| + | velocidad += 10 | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | No necesitamos pasar `velocidad` como parámetro porque pertenece al propio objeto. | ||
| + | |||
| + | ==== Constructor primario ==== | ||
| + | |||
| + | Cuando creamos un objeto normalmente queremos proporcionar sus datos iniciales. | ||
| + | |||
| + | Para ello utilizamos un **constructor**. | ||
| + | |||
| + | La forma más habitual en Kotlin es utilizar un **constructor primario**, que se declara directamente en la cabecera de la clase: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona(val nombre: String, var edad: Int) { | ||
| + | |||
| + | } </ | ||
| + | |||
| + | Ahora debemos proporcionar esos valores al crear el objeto: | ||
| + | |||
| + | <code kotlin> | ||
| + | val persona = Persona(" | ||
| + | </ | ||
| + | |||
| + | Podemos acceder posteriormente a ellos: | ||
| + | |||
| + | <code kotlin> | ||
| + | println(persona.nombre) | ||
| + | println(persona.edad) | ||
| + | </ | ||
| + | |||
| + | Resultado: | ||
| + | |||
| + | < | ||
| + | Ana | ||
| + | 20 | ||
| + | </ | ||
| + | |||
| + | La sintaxis completa del constructor podría escribirse utilizando la palabra `constructor`: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona constructor(val nombre: String, var edad: Int) { | ||
| + | |||
| + | } </ | ||
| + | |||
| + | Sin embargo, normalmente podemos omitirla: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona(val nombre: String, var edad: Int) { | ||
| + | |||
| + | } </ | ||
| + | |||
| + | Esta es la forma que utilizaremos habitualmente. | ||
| + | |||
| + | ==== Parámetros y propiedades del constructor ==== | ||
| + | |||
| + | Existe una diferencia importante entre escribir: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona(nombre: | ||
| + | </ | ||
| + | |||
| + | y: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona(val nombre: String) | ||
| + | </ | ||
| + | |||
| + | En el segundo caso `nombre` se convierte en una **propiedad del objeto**. | ||
| + | |||
| + | Por ello podemos hacer: | ||
| + | |||
| + | <code kotlin> | ||
| + | val persona = Persona(" | ||
| + | |||
| + | println(persona.nombre) </ | ||
| + | |||
| + | Sin `val` o `var`, el parámetro del constructor no se convierte automáticamente en una propiedad accesible del objeto. | ||
| + | |||
| + | Por tanto: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona( | ||
| + | val nombre: String, | ||
| + | var edad: Int | ||
| + | ) | ||
| + | </ | ||
| + | |||
| + | es una forma muy habitual de declarar simultáneamente: | ||
| + | |||
| + | * Los parámetros necesarios para crear el objeto. | ||
| + | * Las propiedades que almacenará. | ||
| + | |||
| + | ==== Valores por defecto ==== | ||
| + | |||
| + | Los parámetros del constructor pueden tener valores por defecto: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona( | ||
| + | val nombre: String = " | ||
| + | var edad: Int = 0 | ||
| + | ) | ||
| + | </ | ||
| + | |||
| + | Ahora podemos crear objetos de diferentes maneras: | ||
| + | |||
| + | <code kotlin> | ||
| + | val persona1 = Persona() | ||
| + | |||
| + | val persona2 = Persona(" | ||
| + | |||
| + | val persona3 = Persona(" | ||
| + | |||
| + | Los valores serán: | ||
| + | |||
| + | < | ||
| + | persona1 -> nombre = " | ||
| + | |||
| + | persona2 -> nombre = " | ||
| + | |||
| + | persona3 -> nombre = " | ||
| + | |||
| + | También podemos utilizar argumentos con nombre: | ||
| + | |||
| + | <code kotlin> | ||
| + | val persona = Persona( | ||
| + | edad = 25, | ||
| + | nombre = " | ||
| + | ) | ||
| + | </ | ||
| + | |||
| + | ==== Propiedades adicionales ==== | ||
| + | |||
| + | No todas las propiedades tienen que declararse en el constructor. | ||
| + | |||
| + | Podemos declarar otras propiedades dentro del cuerpo de la clase: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona( | ||
| + | val nombre: String, | ||
| + | val anioNacimiento: | ||
| + | ) { | ||
| + | |||
| + | ``` | ||
| + | val mayoriaEdad = 18 | ||
| + | |||
| + | var activo = true | ||
| + | ``` | ||
| + | |||
| + | } </ | ||
| + | |||
| + | También podemos calcular una propiedad utilizando los datos recibidos por el constructor: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Rectangulo( | ||
| + | val base: Double, | ||
| + | val altura: Double | ||
| + | ) { | ||
| + | |||
| + | ``` | ||
| + | val area = base * altura | ||
| + | ``` | ||
| + | |||
| + | } </ | ||
| + | |||
| + | Uso: | ||
| + | |||
| + | <code kotlin> | ||
| + | val rectangulo = Rectangulo(10.0, | ||
| + | |||
| + | println(rectangulo.area) </ | ||
| + | |||
| + | Resultado: | ||
| + | |||
| + | < | ||
| + | 50.0 | ||
| + | </ | ||
| + | |||
| + | ==== Bloque init ==== | ||
| + | |||
| + | En ocasiones necesitamos ejecutar instrucciones cuando se crea un objeto. | ||
| + | |||
| + | Para ello podemos utilizar un bloque `init`. | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona( | ||
| + | val nombre: String, | ||
| + | var edad: Int | ||
| + | ) { | ||
| + | |||
| + | ``` | ||
| + | init { | ||
| + | println(" | ||
| + | } | ||
| + | ``` | ||
| + | |||
| + | } </ | ||
| + | |||
| + | Cuando hacemos: | ||
| + | |||
| + | <code kotlin> | ||
| + | val persona = Persona(" | ||
| + | </ | ||
| + | |||
| + | se ejecutará automáticamente el bloque `init`. | ||
| + | |||
| + | Podemos acceder desde él a los parámetros y propiedades: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona( | ||
| + | val nombre: String, | ||
| + | var edad: Int | ||
| + | ) { | ||
| + | |||
| + | ``` | ||
| + | init { | ||
| + | println(" | ||
| + | println(" | ||
| + | } | ||
| + | ``` | ||
| + | |||
| + | } </ | ||
| + | |||
| + | ==== Validación durante la inicialización ==== | ||
| + | |||
| + | Uno de los usos del bloque `init` es comprobar que los datos utilizados para crear un objeto sean correctos. | ||
| + | |||
| + | Por ejemplo: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona( | ||
| + | val nombre: String, | ||
| + | var edad: Int | ||
| + | ) { | ||
| + | |||
| + | ``` | ||
| + | init { | ||
| + | require(edad >= 0) { | ||
| + | "La edad no puede ser negativa" | ||
| + | } | ||
| + | } | ||
| + | ``` | ||
| + | |||
| + | } </ | ||
| + | |||
| + | Esto sería válido: | ||
| + | |||
| + | <code kotlin> | ||
| + | val persona = Persona(" | ||
| + | </ | ||
| + | |||
| + | Pero: | ||
| + | |||
| + | <code kotlin> | ||
| + | val persona = Persona(" | ||
| + | </ | ||
| + | |||
| + | provocaría un error porque no se cumple la condición establecida mediante `require()`. | ||
| + | |||
| + | Otro ejemplo: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Producto( | ||
| + | val nombre: String, | ||
| + | val precio: Double | ||
| + | ) { | ||
| + | |||
| + | ``` | ||
| + | init { | ||
| + | require(nombre.isNotBlank()) { | ||
| + | "El nombre no puede estar vacío" | ||
| + | } | ||
| + | |||
| + | require(precio >= 0) { | ||
| + | "El precio no puede ser negativo" | ||
| + | } | ||
| + | } | ||
| + | ``` | ||
| + | |||
| + | } </ | ||
| + | |||
| + | <WRAP info> | ||
| + | `require()` permite indicar una condición que debe cumplirse. | ||
| + | |||
| + | Si la condición es falsa, Kotlin lanza una excepción indicando que el argumento proporcionado no es válido. | ||
| + | |||
| + | No es necesario profundizar todavía en las excepciones para poder utilizar esta validación básica. </ | ||
| + | |||
| + | ==== Constructores secundarios ==== | ||
| + | |||
| + | Una clase puede tener además **constructores secundarios**. | ||
| + | |||
| + | Se declaran mediante `constructor` dentro del cuerpo de la clase. | ||
| + | |||
| + | Por ejemplo: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona( | ||
| + | val nombre: String, | ||
| + | var edad: Int | ||
| + | ) { | ||
| + | |||
| + | ``` | ||
| + | constructor(nombre: | ||
| + | ``` | ||
| + | |||
| + | } </ | ||
| + | |||
| + | Ahora podemos crear: | ||
| + | |||
| + | <code kotlin> | ||
| + | val persona1 = Persona(" | ||
| + | |||
| + | val persona2 = Persona(" | ||
| + | |||
| + | En el segundo caso se utiliza el constructor secundario: | ||
| + | |||
| + | <code kotlin> | ||
| + | constructor(nombre: | ||
| + | </ | ||
| + | |||
| + | que llama al constructor primario proporcionando: | ||
| + | |||
| + | < | ||
| + | nombre -> valor recibido | ||
| + | edad -> 0 | ||
| + | </ | ||
| + | |||
| + | <WRAP important> | ||
| + | Si existe un constructor primario, los constructores secundarios deben terminar delegando en él mediante `this(...)`. | ||
| + | </ | ||
| + | |||
| + | No obstante, Kotlin permite solucionar muchas situaciones mediante **valores por defecto**, por lo que no necesitaremos constructores secundarios con tanta frecuencia como en otros lenguajes. | ||
| + | |||
| + | Por ejemplo, en el caso anterior probablemente sea más sencillo escribir: | ||
| + | |||
| + | <code kotlin> | ||
| + | class Persona( | ||
| + | val nombre: String, | ||
| + | var edad: Int = 0 | ||
| + | ) | ||
| + | </ | ||
| + | |||
| + | ===== Ejemplo completo: clase Producto ===== | ||
| + | |||
| + | Vamos a representar un producto de una tienda. | ||
| + | |||
| + | Cada producto tendrá: | ||
| + | |||
| + | * Nombre. | ||
| + | * Precio. | ||
| + | * Stock. | ||
| + | |||
| + | Además podrá: | ||
| + | |||
| + | * Mostrar su información. | ||
| + | * Vender unidades. | ||
| + | * Reponer unidades. | ||
| + | * Calcular el valor total del stock. | ||
| + | |||
| + | <code kotlin> | ||
| + | class Producto( | ||
| + | val nombre: String, | ||
| + | val precio: Double, | ||
| + | var stock: Int = 0 | ||
| + | ) { | ||
| + | |||
| + | ``` | ||
| + | init { | ||
| + | require(nombre.isNotBlank()) { | ||
| + | "El nombre no puede estar vacío" | ||
| + | } | ||
| + | |||
| + | require(precio >= 0) { | ||
| + | "El precio no puede ser negativo" | ||
| + | } | ||
| + | |||
| + | require(stock >= 0) { | ||
| + | "El stock no puede ser negativo" | ||
| + | } | ||
| + | } | ||
| + | |||
| + | fun vender(cantidad: | ||
| + | |||
| + | if (cantidad <= 0) { | ||
| + | println(" | ||
| + | } else if (cantidad > stock) { | ||
| + | println(" | ||
| + | } else { | ||
| + | stock -= cantidad | ||
| + | println(" | ||
| + | } | ||
| + | } | ||
| + | |||
| + | fun reponer(cantidad: | ||
| + | |||
| + | if (cantidad > 0) { | ||
| + | stock += cantidad | ||
| + | } | ||
| + | } | ||
| + | |||
| + | fun calcularValorStock(): | ||
| + | return precio * stock | ||
| + | } | ||
| + | |||
| + | fun mostrarInformacion() { | ||
| + | println(" | ||
| + | println(" | ||
| + | println(" | ||
| + | println(" | ||
| + | } | ||
| + | ``` | ||
| + | |||
| + | } </ | ||
| + | |||
| + | Podemos utilizarla: | ||
| + | |||
| + | <code kotlin> | ||
| + | fun main() { | ||
| + | |||
| + | ``` | ||
| + | val teclado = Producto( | ||
| + | nombre = " | ||
| + | precio = 59.95, | ||
| + | stock = 10 | ||
| + | ) | ||
| + | |||
| + | teclado.mostrarInformacion() | ||
| + | |||
| + | teclado.vender(3) | ||
| + | |||
| + | teclado.reponer(5) | ||
| + | |||
| + | teclado.mostrarInformacion() | ||
| + | ``` | ||
| + | |||
| + | } </ | ||
| + | |||
| + | En este ejemplo podemos identificar claramente los dos elementos principales de un objeto. | ||
| + | |||
| + | **Estado del objeto:** | ||
| + | |||
| + | < | ||
| + | nombre | ||
| + | precio | ||
| + | stock | ||
| + | </ | ||
| + | |||
| + | **Comportamiento del objeto:** | ||
| + | |||
| + | < | ||
| + | vender() | ||
| + | reponer() | ||
| + | calcularValorStock() | ||
| + | mostrarInformacion() | ||
| + | </ | ||
| + | |||
| + | ===== Referencias entre objetos ===== | ||
| + | |||
| + | Una variable que contiene un objeto contiene una **referencia a ese objeto**. | ||
| + | |||
| + | Por ejemplo: | ||
| + | |||
| + | <code kotlin> | ||
| + | val producto1 = Producto( | ||
| + | " | ||
| + | 50.0, | ||
| + | 10 | ||
| + | ) | ||
| + | |||
| + | val producto2 = producto1 </ | ||
| + | |||
| + | En este caso no hemos creado dos productos independientes. | ||
| + | |||
| + | `producto1` y `producto2` hacen referencia al **mismo objeto**. | ||
| + | |||
| + | Por tanto: | ||
| + | |||
| + | <code kotlin> | ||
| + | producto2.stock = 5 | ||
| + | |||
| + | println(producto1.stock) </ | ||
| + | |||
| + | mostrará: | ||
| + | |||
| + | < | ||
| + | 5 | ||
| + | </ | ||
| + | |||
| + | Esto es diferente de lo que ocurre con tipos sencillos como `Int`: | ||
| + | |||
| + | <code kotlin> | ||
| + | var numero1 = 10 | ||
| + | var numero2 = numero1 | ||
| + | |||
| + | numero2 = 20 | ||
| + | |||
| + | println(numero1) </ | ||
| + | |||
| + | El resultado continúa siendo: | ||
| + | |||
| + | < | ||
| + | 10 | ||
| + | </ | ||
| + | |||
| + | <WRAP important> | ||
| + | Comprender que los objetos se manejan mediante referencias será importante posteriormente cuando trabajemos con objetos, colecciones y aplicaciones Android. | ||
| + | </ | ||
| + | |||
| + | ===== Ejercicio — Gestión de vehículos ===== | ||
| + | |||
| + | Crea una clase denominada: | ||
| + | |||
| + | <code kotlin> | ||
| + | Vehiculo | ||
| + | </ | ||
| + | |||
| + | Cada vehículo debe almacenar: | ||
| + | |||
| + | * Matrícula. | ||
| + | * Marca. | ||
| + | * Modelo. | ||
| + | * Kilómetros. | ||
| + | * Nivel de combustible. | ||
| + | * Capacidad máxima del depósito. | ||
| + | |||
| + | Por ejemplo: | ||
| + | |||
| + | <code kotlin> | ||
| + | val coche = Vehiculo( | ||
| + | matricula = "1234 ABC", | ||
| + | marca = " | ||
| + | modelo = " | ||
| + | kilometros = 50000, | ||
| + | combustible = 30.0, | ||
| + | capacidadDeposito = 50.0 | ||
| + | ) | ||
| + | </ | ||
| + | |||
| + | La clase debe proporcionar las siguientes funciones: | ||
| + | |||
| + | <code kotlin> | ||
| + | mostrarInformacion() | ||
| + | |||
| + | repostar(litros) | ||
| + | |||
| + | realizarViaje(kilometros, | ||
| + | |||
| + | La función `repostar()` debe comprobar: | ||
| + | |||
| + | * Que la cantidad sea positiva. | ||
| + | * Que el depósito no supere su capacidad máxima. | ||
| + | |||
| + | Por ejemplo, si quedan 40 litros en un depósito de 50 y hacemos: | ||
| + | |||
| + | <code kotlin> | ||
| + | coche.repostar(20.0) | ||
| + | </ | ||
| + | |||
| + | el depósito deberá quedar en: | ||
| + | |||
| + | < | ||
| + | 50 litros | ||
| + | </ | ||
| + | |||
| + | La función: | ||
| + | |||
| + | <code kotlin> | ||
| + | realizarViaje(kilometros, | ||
| + | </ | ||
| + | |||
| + | recibirá: | ||
| + | |||
| + | * Distancia que se quiere recorrer. | ||
| + | * Consumo del vehículo en litros cada 100 km. | ||
| + | |||
| + | Por ejemplo: | ||
| + | |||
| + | <code kotlin> | ||
| + | coche.realizarViaje( | ||
| + | kilometros = 200, | ||
| + | consumo = 6.5 | ||
| + | ) | ||
| + | </ | ||
| + | |||
| + | El programa deberá calcular el combustible necesario: | ||
| + | |||
| + | < | ||
| + | combustibleNecesario = kilometros * consumo / 100 | ||
| + | </ | ||
| + | |||
| + | Si existe combustible suficiente: | ||
| + | |||
| + | * Restar el combustible consumido. | ||
| + | * Aumentar el kilometraje del vehículo. | ||
| + | * Mostrar un mensaje indicando que el viaje se ha realizado. | ||
| + | |||
| + | Si no existe combustible suficiente: | ||
| + | |||
| + | * No modificar el kilometraje. | ||
| + | * No modificar el combustible. | ||
| + | * Mostrar un mensaje indicando que no existe combustible suficiente. | ||
| + | |||
| + | Además, utiliza un bloque `init` para comprobar que: | ||
| + | |||
| + | * Los kilómetros iniciales no sean negativos. | ||
| + | * El combustible no sea negativo. | ||
| + | * La capacidad del depósito sea mayor que cero. | ||
| + | |||
| + | Finalmente, crea al menos **tres vehículos diferentes** y realiza distintas operaciones sobre ellos. | ||
| + | |||
| + | ===== Ejercicio de ampliación ===== | ||
| + | |||
| + | Crea una clase `Alumno` que almacene: | ||
| + | |||
| + | < | ||
| + | nombre | ||
| + | apellidos | ||
| + | edad | ||
| + | notas | ||
| + | </ | ||
| + | |||
| + | Las notas pueden almacenarse en: | ||
| + | |||
| + | <code kotlin> | ||
| + | val notas = mutableListOf< | ||
| + | </ | ||
| + | |||
| + | La clase deberá proporcionar las funciones: | ||
| + | |||
| + | <code kotlin> | ||
| + | agregarNota(nota) | ||
| + | |||
| + | calcularMedia() | ||
| + | |||
| + | estaAprobado() | ||
| + | |||
| + | mostrarInformacion() </ | ||
| + | |||
| + | `agregarNota()` solamente deberá aceptar valores entre `0` y `10`. | ||
| + | |||
| + | `calcularMedia()` devolverá la media de las notas del alumno. | ||
| + | |||
| + | `estaAprobado()` devolverá un `Boolean` indicando si la media es igual o superior a `5`. | ||
| + | |||
| + | `mostrarInformacion()` deberá producir una salida similar a: | ||
| + | |||
| + | < | ||
| + | Alumno: Ana García | ||
| + | Edad: 20 | ||
| + | Notas: 7.5, 8.0, 6.5, 9.0 | ||
| + | Media: 7.75 | ||
| + | Resultado: APROBADO | ||
| + | </ | ||
| + | |||
| + | Crea posteriormente varios objetos `Alumno`, añade diferentes notas y muestra sus resultados. | ||
| + | |||
| ---- | ---- | ||
| (c) {{date> %Y}} Fernando Valdeón | (c) {{date> %Y}} Fernando Valdeón | ||
anexos/kotlin2.1789981519.txt.gz · Última modificación: por fernando
