Desarrollo de aplicaciones multiplataforma


Módulo de programación.

2021-2022
### Eduardo Fernandez Oliver `Linked-in` https://www.linkedin.com/in/efoliver/
efernandez@iesrafaelalberti.es
eferoli398@g.educaanda.es ![](images/logo-kotlin.png)
# Contenido - Aprender a programar - Herramientas: - Lenguaje de programación: Kotlin - Entornos de desarrollo integrados (IDE) - Sistema de control de versiones - Test y marcos de trabajo (Frameworks)
# Evaluación - Resultados de evaluación (RA) - Criterios de evaluación (CE) - Actividades de clases, Prácticas y Pruebas
## Resultados de evaluación (RA) 1 1. Conoce la estructura de un programa informático, identificando y relacionando los elementos propios del lenguaje de programación utilizado. 2. Escribe y prueba programas sencillos, reconociendo y aplicando los fundamentos de la programación orientada a objetos. 3. Escribe y depura código, analizando y utilizando las estructuras de control del lenguaje. 4. Desarrolla programas organizados en clases analizando y aplicando los principios de la programación orientada a objetos. 5. Realiza operaciones de entrada y salida de información, utilizando procedimientos específicos del lenguaje y librerías de clases.
## Resultados de evaluación (RA) 2 6. Escribe programas que manipulen información seleccionando y utilizando tipos avanzados de datos. 7. Desarrolla programas aplicando características avanzadas de los lenguajes orientados a objetos y del entorno de programación. 8. Utiliza bases de datos orientadas a objetos, analizando sus características y aplicando técnicas para mantener la persistencia de la información. 9. Gestiona información almacenada en bases de datos relacionales manteniendo la integridad y consistencia de los datos.
## Conocimientos previos - ¿Eres repetidor? ¿Qué fue lo que más te costó? - ¿Conoces un lenguaje? ¿Cuáles? ¿Preferencias? - ¿Conoces Kotlin? ¿Para qué sirve? - ¿Sabes que es git, IDE, junit? - ¿Has trabajado en el mundo de la informática? - ¿Nivel de inglés?
## Metodología - Aprender haciendo. - Actividades prácticas que acompañan la teoria.
## Herramientas 1 (IDE) - Descargar [Toolbox](https://www.jetbrains.com/toolbox-app/) e instalar IntelliJ IDEA Edu. - Instala el curso Atomic Kotlin - New Course: Stepik -> AtomicKotlin - Solución de problema al compilar - Sustituir el fichero build.gradle por [este](https://github.com/svtk/AtomicKotlinCourse/blob/bb069e4a36cf7467b1481788a9cc2ace0772648e/build.gradle) - Logarse en Stepik para que haga seguimiento de los avances. (github)
## Herramientas 2 (SCV) - Correo en @iesrafaelalberti.es - Dar de alta en cuenta en github - Aula virtual: - Poner foto - Cambiar email
## Mas allá - Aula atéca - Aula de emprendimiento
# Unidad 1 ## Introducción a la programación en Kotlin
## Resultado de Aprendizaje 1 > Conoce la estructura de un programa informático, identificando y relacionando los elementos propios del lenguaje de programación utilizado.
## Criterios de evaluación - a) Se han identificado los bloques que componen la estructura de un programa informático. - b) Se han creado proyectos de desarrollo de aplicaciones. - c) Se han utilizado entornos integrados de desarrollo. - d) Se han identificado los distintos tipos de variables y la utilidad específica de cada uno. - e) Se ha modificado el código de un programa para crear y utilizar variables. - f) Se han creado y utilizado constantes y literales. - g) Se han clasificado, reconocido y utilizado en expresiones los operadores del lenguaje. - h) Se ha comprobado el funcionamiento de las conversiones de tipos explícitas e implícitas. - i) Se han introducido comentarios en el código.
## Contenidos mínimos: **Identificación de los elementos de un programa informático:** - Estructura y bloques fundamentales. - Variables. - Tipos de datos. - Literales. - Constantes. - Operadores y expresiones. - Conversiones de tipo. - Comentarios. - Entornos integrados de desarrollo. - Definición y tipos. Entornos comerciales y de Softwarelibre. - Instalación y descripción de entornos integrados dedesarrollo. - Creación de proyectos. Estructura y componentes.
*********************
## La programación 1 - [Definición](https://es.wikipedia.org/wiki/Programaci%C3%B3n) - Es el **proceso** por el cual se desarrolla un **programa**, haciendo uso de herramientas como un **lenguajes de programación** y de otra que sea capaz de “traducirlo” a lo que se conoce como lenguaje de máquina, que puede "comprender" el microprocesador. - **Ciclo de vida**: Entender el problema, recopilar requisitos, Planificar, Diseñar, Programar, Probar, Desplegar, Mantener.
## La programación 2 ![](images/cdv.png)
## Ordenador 1 - **Máquina** electrónica, analógica o digital, dotada de una memoria de gran capacidad y de métodos de tratamiento de la información, capaz de resolver problemas matemáticos y lógicos mediante la utilización de programas informáticos. - Un ordenador **ejecuta programas**, que son un conjunto de instrucciones representadas mediante un lenguaje de programación y datos que se ejecutan de forma secuencial y que a partir de unos datos de entrada producen una salida. Para ejecutar esos programas el ordenador sigue esta estructura básica:
## Ordenador 2 ![](images/Arquitectura_von_Neumann.png)
## Programa 1 - Un programa informático es una secuencia de instrucciones, escritas para realizar una tarea específica en un computador. - **Algoritmo**: En términos de programación, un algoritmo es una secuencia de pasos lógicos que permiten solucionar un problema.
## Programa 2 ![](images/flujo.png)
## Lenguaje de programación - [TIOBE](https://www.tiobe.com/tiobe-index/) - [Encuesta stackoverflow](https://insights.stackoverflow.com/survey/2021#overview) - ¿Que lenguajes de programación conoces? - ¿Tienes alguna preferencia? - ¿Cuás crees que se adapta mejor a [multiplataforma](https://kotlinlang.org/docs/mpp-intro.html)?
## [Kotlin](https://es.wikipedia.org/wiki/Kotlin) 1 - Kotlin Apareció en 2016 - Propietario por JetBrains, al giual que IntelliJ IDEA y Android Studio. - Se ejecuta sobre la JVM de Java. - Intenta mejorar Java, pero influido por Java, Scala, Groovy, C# - Google lo nombra en el 2017 lenguaje oficial para Android. - Totalmente interoperable con Java. - [Kotlin for Beginners](https://docs.google.com/document/d/1XIJaV3zhn-tJhDc_6Kr00lmTo5zCBuES3Yt67wX752M/edit#heading=h.cbodwtv878mx)
## [Kotlin](https://es.wikipedia.org/wiki/Kotlin) 2 ~~~ fun main() { val scope = "mundo" println("Hola, $scope!") } ~~~ https://play.kotlinlang.org/byExample
# Comenzamos.
## Instalar IDE (RA1.c) - Descargar e Instalar el IDE siguiendo el proceso - Instalar Jet Brains Tools box, usarlo para instalar **IntelliJ Idea Edu**. - URL https://www.jetbrains.com/es-es/idea/download
## Bloques básicos (RA1.a) 1 ![](images/bloquesPrograma.png) { width=50% }
## Bloques básicos (RA1.a) 2 - Main, punto de entrada: Inicio del flujo de ejecución de un programa + https://kotlinlang.org/docs/basic-syntax.html#program-entry-point - Paquetes e import: Agrupa clases, e incorpora clases para su uso, respectivamente + https://kotlinlang.org/docs/basic-syntax.html#package-definition-and-imports - Funciones: Bloques de código con nombre que pueden ser reutilizados + https://kotlinlang.org/docs/basic-syntax.html#functions
## Crear proyecto (RA1.b) - Como crear un proyecto para realizar una aplicación + Sigue los pasos [aquí](https://kotlinlang.org/docs/jvm-get-started.html#create-an-application) - **Actividad**: + Lanzar el IDE y crear un proyecto. + Proyecto tipo: Kotlin + Nombre: Calc + Plantilla: Aplicación de consola + Junit 5
## Compilador, linea de comandos 1 - Instalar el compilador desde linea de comandos. + Desde [esta pagina](https://kotlinlang.org/docs/command-line.html) puedes seguir los pasos - Ten en cuenta el S.O. + Si windows, instalalo manualmente, configura el path adecuadamente + Si linux, usa SDKMAN.
## Compilador, linea de comandos 2 - Mira [aquí](https://github.com/JetBrains/kotlin/releases/tag/v1.5.31) - Fijate en los archivos que se pueden descargar. ¿Cual es la diferencia?: + kotlin-compiler-xxxx.zip + kotlin-native-xxxxxx.zip - Siguiendo los pasos + crea un programa básico con un editor. + compilalo: ```kotlinc``` + ejecutalo: ```Kotlin``` - Mira la opción de ejecución REPL ¿Que és?
## Gradle, 1 - Instalar gradle. + Desde [esta pagina](https://gradle.org/install/) puedes seguir los pasos - Ten en cuenta el S.O. + Si windows, instalalo manualmente, configura el path adecuadamente + Si linux, usa SDKMAN.
## Gradle, 2 - Create una apps en kotlin usando gradle. - ```gradle init``` - [Diferencia](https://www.it-swarm-es.com/es/gradle/diferencia-entre-el-uso-de-gradlew-y-gradle/828397775/) entre gradle y gradlew. - Mira [aquí](https://docs.gradle.org/current/samples/sample_building_kotlin_applications.html) para seguir los pasos.
## Gradle, 3 - Ejecuta la aplicación + ```./gradlew run``` - Ejecuta los test + ```./gradlew test``` - Cambia el test para que compruebe que el método greeting devuelve "hola tu_nombre" - Ejecuta los test + ```./gradlew test``` - Cambia la aplicación para que pase el test correctamente. - Otras tareas + ```./gradlew build --scan //Deja constancia de los tiempos de construcción``` + ```./gradlew tasks // Lista las tareas de gradle```
## Comentarios (RA1.i) - De una línea **//** y multilíne **/\* \*/** - https://kotlinlang.org/docs/basic-syntax.html#comments
## Variables y Tipos (RA1.d) - Variables y ámbitos (scope) de variables. + https://kotlinlang.org/docs/basic-syntax.html#variables + https://play.kotlinlang.org/byExample/01_introduction/03_Variables - Constantes + https://kotlinlang.org/docs/basic-types.html#literal-constants - Tipos (numbers, booleans, characters, strings, and arrays) + https://kotlinlang.org/docs/basic-types.html
## Actividad (RA1.e) (RA1.f) - Modificar una aplicación que usa constantes y literales para que use variables. - Hacer uso de readLine(). - Crear una función: ```fun suma(a:Int, b:Int): Int```
## Crear test con Junit. - Puedes seguir los pasos aquí: + https://kotlinlang.org/docs/jvm-test-using-junit.html + https://kotlinlang.org/docs/mpp-run-tests.html#test-shared-code - **Actividad**: Hacer un test a la función suma.
## Conversión entre tipos (RA1.h) - explícitas e implícitas + https://kotlinlang.org/docs/basic-syntax.html#type-checks-and-automatic-casts + https://kotlinlang.org/docs/basic-types.html#explicit-conversions + https://kotlinlang.org/docs/typecasts.html#smart-casts
## Operadores (RA1.g) 1 - Aquí puedes ver los tipos de operadores más usados en kotlin: + https://kotlinlang.org/docs/basic-types.html#operations + https://www.develou.com/operadores-en-kotlin/
## Operadores (RA1.g) 2 - Aritméticos + (+) ```val suma:Int = 5 + 2 // 8``` + (-) ```val resta:Int = 5 - 2 // 3``` + (\*) ```val multipli:Int = 5 \* 2 // 10``` + (/) ```val divide:Int = 5 / 2 // 2``` + (%) ```val resto:Int = 5 % 2 // 1```
## Operadores (RA1.g) 3 - Comparación + (==) ```val igual:Boolean = 5 == 2 // False``` + (!=) ```val distinto:Boolean = 5 != 2 // True``` + (>, >=) ```val mayorIgual:Boolean = 5 >= 2 // True``` + (<, <=) ```val menor:Boolean = 5 < 2 // False```
## Operadores (RA1.g) 3 - Lógicos + (&&) ```val conjuncion:Boolean = igual && mayorIgual // true``` + (!!) ```val disyuncion:Boolean = distinto || menor // True``` + (!) ```val mayorIgual:Boolean = ! disyuncion // False```
## Operadores (RA1.g) 4 - Operador in
## Valores Nulos - Intenta evitar NullPointerException - No nos deja asignar variables a nulo, tenemos que forzarlo con ? - ```val nullString: String = readline() ?: "" //Operador Elvis ?:``` - ```val nullString: String? = null //Declaración de nulo usando ?``` - ```nullString?.let { println(nullString) } // solo se ejecuta si nullString no es nulo ``` - ```nullString?.let { ... } ?: run { println("la cadena es nula") } // Codigo a ejecutar si es nulo ``` - ```nullString?.let { ... } ?: run { println(nullString!!) } // con !! asumimos el riesgo de que sea nulo ```
## Entrada (teclado) y salida (pantalla) - Puedes usar las funciones `println` y `print` para mostrar en pantalla un texto. - Puedes usar la función `readline()` para leer desde teclado una linea.
## Funciones 1 - Definición: ```fun nombreFuncion(parametro:Int): Unit { }``` - Las funciones SOLO DEBEN HACER UNA COSA - El nombre de la función tiene que describir qué hace.
## Funciones 2 ~~~Kt fun callMe() { println("Printing from callMe() function.") println("This is cool (still printing from inside).") } fun main(args: Array) { callMe() println("Printing outside from callMe() function.") } ~~~ ![](images/kotlin-function-call.webp)
# Unidad 2 ## Estructuras de programación básicas
## Resultado de Aprendizaje 3 > Escribe y depura código, analizando y utilizando las estructuras de control del lenguaje.
## Criterios de evaluación - a) Se ha escrito y probado código que haga uso de estructuras de selección. - b) Se han utilizado estructuras de repetición. - c) Se han utilizado estructuras de repetición. - d) Se han reconocido las posibilidades de las sentencias de salto. - e) Se ha escrito código utilizando control de excepciones. - f) Se han creado programas ejecutables utilizando diferentes estructuras de control. - g) Se han probado y depurado los programas. - h) Se ha comentado y documentado el código.
## Contenidos mínimos: **Uso de estructuras de control:** - Estructuras de selección. - Estructuras de repetición. - Estructuras de salto. - Control de excepciones. - Depuración de programas. - El depurador como herramienta de control de errores. - Documentación de programas. - Documentación interna, comentarios. - Documentación externa, diagramas de clases, requisitos, guías, etc.
*********************
## Estructuras de selección. (RA3.a) - [if else](https://cursokotlin.com/capitulo-7-instrucciones-if-else-en-kotlin/) - [when](https://cursokotlin.com/capitulo-8-expresion-when-kotlin/)
## Estructuras de repetición. (RA3.b,c) - Rangos: Representan una secuencia de enteros - rango cerrado: + ```val closedRange = 0..5``` // (1,2...5) - rango mitad cerrado: + ```val halfOpenRange = 0 until 5``` // (1,2...4) - rango decrementado: + ```val decreasingRange = 5 downTo 0``` // (5,4...0) - [Ejemplos](https://parzibyte.me/blog/2019/07/05/ciclos-kotlin-while-for-do-while/)
## Estructuras de repetición. (RA3.b,c) - for: uso de rangos - while: Se comprueba la condición antes de ejecutarse - do while: Al menos se ejecuta una vez - repeat: Número fijo de veces. - [Ejemplos](https://parzibyte.me/blog/2019/07/05/ciclos-kotlin-while-for-do-while/) - Bloques: Variables y ámbitos
## Estructuras de salto. (RA3.d) - return: retornamos de la función actual (o función anónima). - break: terminamos el bucle más cercano. - continue: continuamos con el siguiente paso en el bucle más cercano. - [Ejemplos](http://www.androidcurso.com/index.php/99-kotlin/912-estructuras-de-control-en-kotlin)
## Control de excepciones (RA3.e) 1 - En Kotlin todas las excepciones son subclases de la clase ```Throwable```. - Cada excepción tiene un mensaje, un seguimiento de la pila y una causa opcional. - Para lanzar un objeto de excepción, se utiliza la palabra clave ```throw```: + ```throw Exception("Message")```
## Control de excepciones (RA3.e) 2 - Para capturar una excepción lanzada se utiliza un bloque ```try```: ~~~Kt try {// some code } catch (e: SomeException) {// Captura y maneja la excepción, mas de uno } finally {// optional finally block, Solo uno} ~~~
## Control de excepciones (RA3.e) 3 - Uso de ```try``` como expresión, por tanto puede devolver un valor. ~~~Kt val a: Int? = try { parseInt(input) } catch (e: NumberFormatException) { null } ~~~ - Uso de ```throw``` es una expresión, por tanto se puede usar, por ejemplo, como parte de una 'Elvis expression': ~~~Kt val s = person.name ?: throw IllegalArgumentException("Name required") ~~~
## Ejemplos de programas. (RA3.f) **Actividad** Eje 2.1: Juego del ahorcado
## Depuración de programas. (RA3.g) - Depurar consisten en realizar un seguimiento del funcionamiento del programa + Seguir el flujo de ejecución de aplicación. + Establecer puntos de ruptura + Visualizar los valores de variables. + Visualizar los llamadas entre funciones.
## El depurador como herramienta de control de errores. (RA3.g) - El IDE trae sus propia herramienta. Ejemplos: + [Depurar por primera vez](https://www.jetbrains.com/help/idea/debugging-your-first-java-application.html#stopping-debugger) + [Depurar un flujo](https://kotlinlang.org/docs/debug-flow-with-idea.html#debug-a-kotlin-flow-with-two-coroutines)
## Documentación de programas. (RA3.h) - Documentación interna, comentarios. + https://runebook.dev/es/docs/kotlin/docs/reference/kotlin-doc + https://github.com/Kotlin/dokka/blob/master/README.md - Documentación externa: + UML: Lenguaje unificado de modelado. Más info [aquí](https://es.wikipedia.org/wiki/Lenguaje_unificado_de_modelado) + Requisitos: Casos de Uso, Historias de usuarios. + Otra documentación: Manuales de usuario, Manuales de operación, Manuales de administración.
## Prueba teórica práctica. Unidad 1 y 2 - Creación de un proyecto, haciendo uso del IDE. - Usar distintos tipos de variables, constantes y literales - Hacer uso de expresiones y operadores según los tipos del lenguaje, haciendo uso de las conversiones. - Comentar el código. - Uso de estructuras de repetición y selección - Uso de control de excepciones - Depurar y comentar código.
# Unidad 3 ## Introducción a la programación orientada a objetos
## Resultado de Aprendizaje 2 > Escribe y prueba programas sencillos, reconociendo y aplicando los fundamentos de la programación orientada a objetos.
## Criterios de evaluación - a) Se han identificado los fundamentos de la programación orientada a objetos. - b) Se han escrito programas simples. - c) Se han instanciado objetos a partir de clases predefinidas. - d) Se han utilizado métodos y propiedades de los objetos. - e) Se han escrito llamadas a métodos estáticos. - f) Se han utilizado parámetros en la llamada a métodos. - g) Se han incorporado y utilizado librerías de objetos. - h) Se han utilizado constructores. - i) Se ha utilizado el entorno integrado de desarrollo en la creación y compilación de programas simples
## Contenidos mínimos: **Utilización de objetos:** - Características de los objetos. - Instanciación de objetos. - Utilización de métodos. - Utilización de propiedades. - Utilización de métodos estáticos. - Librerías de objetos. Inclusión y uso. - Constructores. - Destrucción de objetos y liberación de memoria. - Entornos de desarrollo para programación orientada a objetos. - Entornos específicos. - Plugins de integración en entornos genéricos.
*********************
## Programación OO (RA2.a) - La [**Programación Orientada a Objetos (POO)**](https://es.wikipedia.org/wiki/Programaci%C3%B3n_orientada_a_objetos): viene a cambiar la forma de programar. Los objetos se utilizan como metáfora para emular las entidades reales del negocio a modelar. - Está basada en varias técnicas como: herencia, cohesión, abstracción, polimorfismo, acoplamiento y encapsulamiento. [mapa mental](https://www.mindomo.com/no/mindmap/programacion-orientada-a-objetos-e256c81f6f8fd0e0654dd70bf05ff657)
## Clases y objetos (RA2.a) - [**Clases:**](https://github.com/revilofe/_kotlin_#clases) Una plantilla para la creación de objetos de datos según un modelo predefinido. - Ej: Persona, Animal, Coche - Las [**clases**](shorturl.at/ikBI9) tienen los siguientes componentes siguientes características, son: - **Atributos/campos**: también variables de instancia, contienen la información de los futuros objetos. Normalmente privadas al objeto. - **Métodos**: implementan la funcionalidad asociada al objeto, son funciones. Pueden acceder a las variables de instancia de la clase directamente. - Cuando se desea realizar una acción sobre un objeto, se dice que se le manda un **mensaje** invocando a un método que realizará la acción.
## Clases y objetos (RA2.a) ![](images/clase.png)
## Clases y objetos (RA2.a) - **Objetos**: Una instancia de la clase, es decir una concreción. Es un ejemplo de esa clase. - Ej: Eduardo, mi perro Tobi, mi coche Ford Fiesta rojo. - Los [**objetos**](shorturl.at/gyACE) tienen las siguientes características, son: - **Identidad**: Lo identifica del resto. - **Comportamiento**: Relacionadlo con su funcionalidad, determina las operaciones que se pueden realizar y con las que responde a los mensajes. - **Estado**: Conjunto de atributos y sus valores en un momento determinado.
## Clases y objetos (RA2.a) ![](images/objetos.png)
## Clases y objetos (RA2.a) ![](images/homerpoo.png)
## En kotlin, clases predefinidas (RA2.c) - En Kotlin, todo es un objeto en el sentido de que podemos llamar funciones y propiedades de miembro en cualquier variable. - `Int` es una clase y `1` es un objeto de la clase `Int`. - Clases predefinidas en Kotlin - https://kotlinlang.org/api/latest/jvm/stdlib/alltypes/ - ***Actividad 3.1:*** Crea un programa en el que uses algún método de la clase Int y sacalo por consola. Haz lo mismo con otra Clase p.Ej: Pair,
## Clases y constructores (RA2.h) - Las clases son los bloques de construcción principales de cualquier lenguaje de programación orientado a objetos. - Las clases son esencialmente tipos personalizados: un grupo de variables y métodos unidos en una estructura coherente. - Para definir una clase se usa la palabra clave `class`. ~~~ class Perro { ... } class Empty // Clase vacia ~~~
## Clases y constructores (RA2.h) En kotlin, las clases pueden contener: - Constructores y bloques `init` - Métodos(Funciones) - Atributos
## Clases y constructores (RA2.h) - Una clase en Kotlin puede tener un [constructor primario](https://github.com/revilofe/_kotlin_#constructor-primario) y uno o más [constructores secundarios](https://github.com/revilofe/_kotlin_#constructor-secundario). - **Primario**: forma parte del encabezado de la clase. - Por defecto, todos los constructores son públicos. Visible donde sea visible la clase. - Si el constructor principal no tiene anotaciones o modificadores de visibilidad, la palabra clave `constructor` se puede omitir. - Este constructor no tiene código, pero se coloca en bloques de inicialización con la palabra clave `init`
## Clases y constructores (RA2.h) - Una clase en Kotlin puede tener un [constructor primario](https://github.com/revilofe/_kotlin_#constructor-primario) y uno o más [constructores secundarios](https://github.com/revilofe/_kotlin_#constructor-secundario). Ej. constructor primario. ~~~ class Persona constructor(nombre: String) { ... } //Crea una clase p = Persona("Jose") //Instancia un objeto de la clase Persona, ~~~
## Clases y constructores (RA2.h) - ***Actividad 3.2:*** Copia y ejecuta el siguiente código. ¿Cómo se crea una instancia de la clase? Create una instancia de clase InitOrderDemo ¿Cuál es el orden de ejecución del código? ~~~ class InitOrderDemo(name: String) { val firstProperty = "First property: $name" init { println("First initializer block that prints ${name}") } val secondProperty = "Second property: ${name.length}" init { println("Second initializer block that prints ${name.length}") } } ~~~
## Clases y constructores e init (RA2.h, RA2.b) - Dentro de los bloques `init` puedes usar la palabra `required` para validar las propiedades o parámetros. ~~~ class Persona(Nombre: String) { init { require(nombre.trim().length > 0) { "Argumento nombre inválido." } } } ~~~ - ***Actividad 3.3:*** Crea una clase coche, que se inicializa con su marca. Ademas y compruebe mediante `require` en el bloque `init` que el argumento marca no es nulo.
## Clases y constructores y propiedades (RA2.d) - Las [variables de instancia o propiedades](https://github.com/revilofe/_kotlin_#propiedades) pueden definirse en el constructor o en el cuerpo de la clase. Si en el constructor principal usamos: - val: Se crearán métodos getter - var: Se crearán métodos [getter y setter](https://github.com/revilofe/_kotlin_#getters-and-setters) - También puedes definirlos tu : ~~~ var stringRepresentation: String get() = this.toString() // parses the string and assigns values to other properties set(value) { setDataFromString(value) } ~~~
## Clases y constructores y propiedades (RA2.d) - Existe un [campo de respaldo](https://github.com/revilofe/_kotlin_#backing-fields) `field`, que solo tiene sentido dentro de getter o setter. ~~~ var selectedColor: Int = someDefaultValue get() = selectedColor set(value) { this.selectedColor = value doSomething() } // Código correcto var selectedColor: Int = someDefaultValue get() = field set(value) { field = value doSomething() } ~~~
## Clases y constructores (RA2.h) - Una clase en Kotlin puede tener un [constructor primario](https://github.com/revilofe/_kotlin_#constructor-primario) y uno o más [constructores secundarios](https://github.com/revilofe/_kotlin_#constructor-secundario). - **Secundario**: puede tener uno o varios, y se definen con la palabra clave `constructor` - Este constructor tiene código, pero se coloca en bloques de inicialización con la palabra clave `init` - Si la clase tiene un constructor primario, el secundario debe delegar en el constructor primario, ya sea directamente o indirectamente usando la palabra clave 'this':
## Clases y constructores (RA2.h) - Una clase en Kotlin puede tener un [constructor primario](https://github.com/revilofe/_kotlin_#constructor-primario) y uno o más [constructores secundarios](https://github.com/revilofe/_kotlin_#constructor-secundario). Ej. constructor secundario. ~~~ class Persona(Nombre: String){ // Constructor secundario, Usamos 'this' para invocar al primario constructor(nombre: String, parent: Person) : this(nombre) { parent.children.add(this) } } ~~~
## Clases y constructores (RA2.h, RA2.b) - ***Actividad 3.4:*** Un coche tiene: - como atributos en su constructor secundario: Marca, Modelo, velocidadMax y color (por defecto blanco) - Crea una clase coche, y compruebe mediante `require` en el bloque `init` que - la velocidad es mayor que 10 y menor que 250.
## Clases y propiedades (RA2.d) - En Kotlin, los campos de la clase se llaman **propiedades** o **variables de instancia** - Las propiedades de una clase pueden declararse como mutables (var), o de inmutables o de sólo lectura (val) - Las propiedades son otros objetos que cualifican al objeto y se acceden a través del `.` y el nombre de la propiedad ~~~Kt class Persona { var ciudad: String var fechanacimiento: Date var codigoPostal: String } p=Persona() println("La ciudad de la persona es es:$p.ciudad") ~~~
## Clases y métodos (RA2.d) - En Kotlin, las funciones definidas dentro de una clase se llaman funciones miembro o métodos de instancia. ~~~ class Persona { var ciudad: String fun soyDe():String = "Soy de $ciudad" } p=Persona() println("De donde eres? La ciudad de la persona es es:$p.soyDe()") ~~~
## Clases y métodos (RA2.b) - ***Actividad 3.5:*** Un coche tiene: - como atributos: Marca, Modelo, #gasolina, Color (defecto blanco), #tanque, #variacionVelocidad=5, #velocidadMax, #factorGasto (Double), #numeroMarchas - como acciones: encender, apagar, iniciar, parar, acelerar, frenar, incrementaMarcha, decrementaMarcha, llenarTanque - además podremos preguntarle por la descripción del coche, el estado, la marcha actual, la velocidad actual - Crea una clase coche, y compruebe mediante `require` en el bloque `init` que - el argumento marca no es nulo. - la velocidad es mayor que 10 y menor que 250. - cualquier otro valor que cras conveniente.
## Métodos (RA2.b) - ***Actividad 3.5:*** Un coche tiene (continuación) - encender: Devuelve true si enciende. Solo enciende si no esta encendido, NO tiene marcha metida y tiene gasolina - apagar: Vuelve al estado inicial ¿necesitas alguna propiedad o método adicional? - iniciar: Solo inicia si esta encendido (No andando). El proceso será establecer marcha 1 y acelerar.
## Métodos (RA2.b) - ***Actividad 3.5:*** Un coche tiene (continuación) - acelerar: Devuelve la velocidad a la que va, solo acelera (+variacionVelocidad) si tiene gasolina, si no envía mensaje y llama al método parar. No puede superar velocidadMax. - ¿cuanto gasta? Siempre que acelera gasta según lo siguiente: marcha->gasto: 1->5, 2->4, 3->3, 4->2, 5->1. Gasto se multiplica por factorGasto - cambia marcha: establece la marcha en la que va: incrementaMarcha, decrementaMarcha. Hay que comprobar que no es menor que 0, ni mayor que el numero de marchas.
## Métodos (RA2.b) - ***Actividad 3.5:*** Un coche tiene (continuación) - frenar: Devuelve la velocidad a la que va, (-variacionVelocidad) cada vez que se frena, ademas en cada frenado se llama a actualizar el gasto de gasolina - parar: Devuelve true al parar. Tiene sentido si esta moviéndose. El proceso sería Llamar a frenar hasta que la velocidad =0, y establece marcha 0.
## Métodos y propiedades de clase (RA2.e) - Similar a los métodos estáticos en Java, un [`companion object`](https://github.com/revilofe/_kotlin_#companion-objects) no está asociado con una instancia de clase, sino con la propia clase. ~~~ class Persona private constructor(var nombre: String, var apellido: String) { // Podemos omitir el nombre del objeto companion object { var count: Int = 0 fun create(nombre: String, apellido: String): Person = Person(nombre, apellido) // Podemos tener bloques 'init' dentro de un 'companion object' init { println("Persona companion object created") } } } val persona = Persona.create("John", "Doe") ~~~
## Métodos y propiedades de clase (RA2.e) - ***Actividad 3.6:*** Añade un método de clase, a la clase coche que compare la velocidad de 2 objetos coche.
*********************
*********************
# Unidad 4 ## Uso de estructuras de datos avanzadas predefinidas
## Resultado de Aprendizaje 6 > Escribe programas que manipulen información seleccionando y utilizando tipos avanzados de datos.
## Criterios de evaluación - a) Se han escrito programas que utilicen arrays - b) Se han reconocido las librerías de clases relacionadas con tipos de datos avanzados. - c) Se han utilizado listas para almacenar y procesar información. - d) Se han utilizado iteradores para recorrer los elementos de las listas. - e) Se han reconocido las características y ventajas de cada una de la colecciones de datos disponibles. - f) Se han creado clases y métodos genéricos.
## Contenidos mínimos: **Aplicación de estructuras predefinidas:** - Estructuras, tipos, definición y usos. - Librerías estándar de objetos. - Arrays, definición, tipos, creación, recorridos, búsquedas y operaciones. - Listas, definición, tipos, creación, recorridos, búsquedas y operaciones. - Otras estructuras: Conjuntos y Mapas. - Tipos genéricos: Definición de clases y métodos genéricos.
*********************
## Librerias (RA6.b) - Kotlin Standard Library - ![left](images/link.png) [https://kotlinlang.org/api/latest/jvm/stdlib/](https://kotlinlang.org/api/latest/jvm/stdlib/) - Las clases y funciones son agrupadas en paquetes (Packages). - Los paquetes agrupan clases, normalmente relacionadas funcionalmente. - Cada clase pertenece a un paquete, y cada paquete tiene un nombre. - Por ej. el paquete `Kotlin.math` contiene .... - Por ej. el paquete `kotlin.collections` contiene ...
## Librerias (RA6.b) ![](images/web-stdlib.png)
- ***Actividad 4.4:*** Consulta la librería standard de Kotlin y recopila información del - Paquete, que tipo de clases contiene, versión en el que se liberó, a qué afecta. - Ejemplo de clases (3 mas características *) que contiene, y para que sirven. Registra el resultado de la investigación en el foro. |paquete|paquete|paquete| |--- |--- |--- | |kotlin *| kotlin.collections *| kotlin.concurrent| |kotlin.comparisons | kotlin.coroutines | kotlin.dom| |kotlin.io | kotlin.math | kotlin.random| |kotlin.ranges | kotlin.reflect | kotlin.sequences| |kotlin.system | kotlin.test | kotlin.text *| |kotlin.time|||
## Las Collections (RA6.a) - Las [**colecciones**](https://github.com/revilofe/_kotlin_#colecciones) nos ayudan a referenciar un conjunto de objetos - Kotlin proporciona su [API](https://es.wikipedia.org/wiki/Interfaz_de_programaci%C3%B3n_de_aplicaciones) de `Collections` - Kotlin tiene dos variantes, mutables e inmutables. - mutables: tiene la capacidad de modificar una colección. (MutableList, MutableSet, HashMap, LinkedHashMap, LinkedHashMap, SortedMap). - inmutable: no se puede modificar. (List, Sets, Maps).
## Las Collections (RA6.a) ![](images/collections.png)
## Las Collections (RA6.a) ![](images/collections2.png)
## Las Collections (RA6.a) Tenemos una variable `x`, que es un contenedor ![](images/variable.png)
## Las Collections (RA6.a) Tenemos un objeto `Int` `5`, almacenado en la memoria ![](images/objetoEntero.png)
## Las Collections (RA6.a) Una variable `x` guarda la referencia al objeto `Int` `5` ![](images/Variable-objetoEntero.png)
## Las Collections (RA6.a) Podemos cambiar la referencia de la variable `x`, apuntando a otro objeto `Int` `6` ![](images/Variable-objetoEntero-Ref.png)
## Las Collections (RA6.a) Podemos tener varias variables `x` y `y` apuntando a un objeto `Int` `5` ![](images/Variables-objetoEntero-Ref.png)
## Las Collections. Arrays (RA6.a) ¿Qué pasa si necesitamos guardar referencias a cientos de objetos `Int`? ![](images/Array.png)
## Las Collections. Arrays (RA6.a) Necesitamos un nuevo objeto `Array` que almacene referencias a esos objetos `Int` Tendremos una variable `myArray` que referencia a ese objeto `Array` ![](images/Array-objetosEnteros.png)
## Las Collections. Arrays (RA6.a) Podrás cambiar la referencia de la variable `myArray`, apuntado a otro objeto `Array` ![](images/Array-objetosEnteros-Ref.png)
## Las Collections. Arrays (RA6.a) Podrás cambiar la referencia de cualquier componente del `Array`, para apuntar a otro objeto `Int` ![](images/Array-objetosEnteros-Ref2.png)
## Las Collections. Arrays (RA6.a) Con los arrays podemos: ![](images/coll-array1.png)
## Las Collections. Arrays (RA6.a) Con los arrays podemos: ![](images/coll-array2.png)
## Las Collections. Arrays (RA6.a) Con los arrays podemos: ![](images/coll-array3.png)
## Las Collections. Arrays (RA6.a) Con los arrays podemos: ![](images/coll-array4.png)
## Las Collections. Arrays (RA6.a) - Constructores de arrays ![left](images/link.png) [Puedes verlo aqui](https://www.techiedelight.com/declare-initialize-array-kotlin/)[ y aqui](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/) - usando la función `arrayOf()` - el constructor `Array(5) {1} // [1, 1, 1, 1, 1]` - constructores para tipos primitivos `IntArray`, `CharArray`, `BooleanArray`, `LongArray` - funciones para tipos primitivos `intArrayOf()`, `charArrayOf()`, `booleanArrayOf()`, `longArrayOf()` - Array/ es similar a Integer[], mientas que IntArray es int[]. - función para array de nulos: `arrayOfNulls/(5)` - función para array vacío: `emptyArray()`
- ***Actividad 4.1:*** Se el compilador. I Las imágenes A y B representan un fichero kotlin. Tu trabajo es ser el compilador y determinar si compilan y se ejecutan sin errores, y si encuentras errores, solucionalos. ![](images/actividad4.1a.png)
- ***Actividad 4.1:*** Se el compilador. II Las imágenes A y B representan un fichero kotlin. Tu trabajo es ser el compilador y determinar si compilan y se ejecutan sin errores, y si encuentras errores, solucionalos. ![](images/actividad4.1b.png)
- ***Actividad 4.2:*** Tienes un conjunto de imanes des ordenados. Ordenalos dentro de la función main para que de la salida que se muestra ![](images/actividad4.2.png)
- ***Actividad 4.2:*** Tienes un conjunto de imanes desordenados. Ordenalos dentro de la función main para que obtener la salida que se muestra ~~~ fun main() { ...... } //Salida Fruit = Banana Fruit = Blueberry Fruit = Pomegranate Fruit = Cherry ~~~
- ***Actividad 4.3:*** Cuando se alcance la linea `//Do stuf`, a que objeto apuntará cada elemento del array. ![](images/actividad4.3.png)
## Las Collections. Otros - `List`, `Set` y `Map` son inmutables por defecto. - `MutableList`, `MutableSet` y `MutableMap` son mutables.
## Las Collections. List (RA6.c) ![](images/List.png) - ![left](images/link.png) [Operaciones especificas de listas](https://kotlinlang.org/docs/list-operations.html) - Permite duplicar valores - Tiene en cuenta el orden. - Puedes usar `==` para comparar dos conjuntos. Será `True` si contiene los mismos elementos y el orden.
## Las Collections. List (RA6.c) ![](images/List-crea.png) - El compilador infiere el tipo, aunque puedes declararlo si quieres.
## Las Collections. List (RA6.c) - Aquí declaramos el tipo ``` val shopping: List<String> shopping = listOf("Tea", "Eggs", "Milk") ``` ![](images/List-usa.png) ``` //Recorre for (item in shopping) println (item) // Si una lista contiene una referencia a un objeto obtienes el indice if (shopping.contains("Milk")) { println(shopping.indexOf("Milk")) //Prints 2 } ```
## Las Collections. MutableList (RA6.c) ![](images/MutableList.png) - Las `MutableList` se crean igual pero usando un constructor especifico. - Estas listas tiene los mismos métodos mas los adicionales para poder modificar la lista. ``` val mShopping = mutableListOf("Tea", "Eggs") //Crea mutable list ```
## Las Collections. MutableList (RA6.c) ``` mShopping.add("Milk") //Añade elemento al final mShopping.add(1, "Milk") //Añade elemento en la posición 1 ``` ![](images/MutableList-add.png)
## Las Collections. MutableList (RA6.c) ``` if (mShopping.contains("Milk")) { Shopping.remove("Milk") //Elimina el elemento Milk } if (mShopping.size > 1) { mShopping.removeAt(1) //Elimina el elemento en la posicion 1 } ```
## Las Collections. MutableList (RA6.c) ![](images/MutableList-remove.png)
## Las Collections. MutableList (RA6.c) ``` if (mShopping.size > 0) { mShopping.set(0, "Coffee") //Añade el elemento a la posición 0 } ``` ![](images/MutableList-replace.png)
- ***Actividad 4.4:*** Tienes un conjunto de imanes des ordenados. Ordenalos dentro de la función main para que de la salida que se muestra ![](images/Actividad4.4.png)
- ***Actividad 4.4:*** Tienes un conjunto de imanes desordenados. Ordenalos dentro de la función main para que obtener la salida que se muestra ~~~ fun main() { ...... } //Salida [Zero, Two, Four, Six] [Two, Four, Six, Eight] [Two, Four, Six, Eight, Ten] [Two, Four, Six, Eight, Ten] ~~~
## Las Collections. Set (RA6.e) ![](images/List-duplicados.png)
## Las Collections. Set (RA6.e) ~~~ val friendSet = setOf("Jim", "Sue","Sue", //Ignorará los valores duplicados "Nick","Nick") ~~~ ![](images/Set.png) - ![left](images/link.png) [Operaciones especificas de conjuntos ](https://kotlinlang.org/docs/set-operations.html) - No permite duplicados. - No tiene en cuenta el orden. - Puedes usar `==` para comparar dos conjuntos. True si contiene los mismos elementos.
## Las Collections. Set (RA6.e) - Duplicado: 1 Igual `hashCode` ![](images/Set-duplicados1.png)
## Las Collections. Set (RA6.e) - Duplicado: 2 Operador `===` (Misma referencia) ~~~ val a = "Sue" val b = a val set = setOf(a, b) ~~~ ![](images/Set-duplicados2.png)
## Las Collections. Set (RA6.e) - Duplicado: 3 Operador `==` (equals function y data class) ~~~ val a = Recipe("Thai Curry") val b = Recipe("Thai Curry") val set = setOf(a, b) ~~~ ![](images/Set-duplicados3.png) - ![left](images/link.png) [Data Class](https://devexperto.com/data-classes-kotlin/)
## Las Collections. Set (RA6.e) - Duplicado: 3 Operador `==` (equals function y data class) ![](images/Set-duplicados4.png)
## Las Collections. MutableSet (RA6.e) * Se pueden crear conjuntos con los metodos `setOf` o con el constructor `Set`. * Para trabajar con Mutables, `mutableSetOf` ~~~ val mFriendSet = mutableSetOf("Jim", "Sue") ~~~ ![](images/MutableSet.png)
## Las Collections. MutableSet (RA6.e) - Trabajar con Mutables. Convertibles a otras colecciones. ~~~ val shoppingSet = mShopping.toSet() //también toMutableSet if (mShopping.size > mShopping.toSet().size) { //mShopping has duplicate values } ~~~ ![](images/MutableSet-copy.png)
## Las Collections. Map (RA6.e) ![](images/Map.png) - ![left](images/link.png) [Operaciones especificas de mapas ](https://kotlinlang.org/docs/map-operations.html) - Utiliza pares `<key,value>` - Puedes tener dos claves referenciando al mismo objeto. - No puedes tener claves duplicadas.
## Las Collections. Map (RA6.e) - Como creamos los `Maps` ![](images/Map-crea.png)
## Las Collections. Map (RA6.e) - Toman la forma `Map<tipo_clave,tipo_valor>` ![](images/Map-crea2.png)
## Las Collections. Map (RA6.e) - Como vas a usar un `Map` - Chequear si contiene una `key` - `containsKey` - Chequear si contiene un `value` - `containsValue` ~~~ recipeMap.containsKey("Recipe1") ~~~ ![](images/Map-containsValue.png)
## Las Collections. Map (RA6.e) - Como vas a usar un `Map` - Recuperar una `value` para una especifica `key` - `get` y `getValue` ![](images/Map-getValue.png)
## Las Collections. Map (RA6.e) - Como vas a usar un `Map` - Recorrer las entradas de un map ~~~ for ((key, value) in recipeMap) { println("Key is $key, value is $value") } ~~~
## Las Collections. MutableMap (RA6.e) - `MutableMap` es un subtipo de `Map`. Por tanto, tiene los mismos métodos. - `MutableMap` tiene métodos adicionales para añadir, modificar y eliminar. - Como creamos los `MutableMap`: usando `mutableMapOf` en lugar de `mapOf` ~~~ val r1 = Recipe("Chicken Soup") val r2 = Recipe("Quinoa Salad") val mRecipeMap = mutableMapOf("Recipe1" to r1, "Recipe2" to r2) ~~~
## Las Collections. MutableMap (RA6.e) - El compilador infiere que es `MutableMap` de tipo `MutableMap<String, Recipe>` ![](images/MutableMap.png)
## Las Collections. MutableMap (RA6.e) - Añadir una entrada usando `put` ![](images/MutableMap-add.png) - Si ya contiene un elemento con la `key` `"Recipe3"`, sustituye el `value` y devuelve el original.
## Las Collections. MutableMap (RA6.e) - Añadir varias entradas usando `putAll` ~~~ val r4 = Recipe("Jambalaya") val r5 = Recipe("Sausage Rolls") val recipesToAdd = mapOf("Recipe4" to r4, "Recipe5" to r5) mRecipeMap.putAll(recipesToAdd) ~~~ > Atención a la sintaxis: `key to value`
## Las Collections. MutableMap (RA6.e) - Borrar entradas usando `remove`. Dos formas: ![](images/MutableMap-remove1.png) ![](images/MutableMap-remove2.png)
## Las Collections. MutableMap (RA6.e) - Vacía el `MutableMap` usando `clear`. ![](images/MutableMap-clear.png)
## Las Collections. MutableMap (RA6.e) - Copiar el `MutableMap` a otro `Map` usando `toMap`. ~~~ val recipeMapCopy = mRecipeMap.toMap() ~~~ - Copiar el `MutableMap` a una `List` usando `toList`. ~~~ val recipelistCopy = mRecipeMap.toListp() ~~~
## Las Collections. MutableMap (RA6.e) - Obtener las entradas de `MutableMap` y `Map` - Devuelve un `Set` o MutableSet` de `Pair<key,value>` - Dependiendo si `mRecipeMap` es `Map` o `MutableMap` respectivamente. ~~~ val recipeEntries = mRecipeMap.entries ~~~ - `keys` devuelve `Set`, o `MutableSet` de las `keys` del `Map` o `MutableMap` respectivamente - `values` devuelve una `Collection` genérica con los `value` del `Map` > Ojo, `entries`, `keys` y `values` contiene los valores actuales del `Map` ~~~ if (mRecipeMap.size > mRecipeMap.values.toSet().size) { //Values duplicados? ¿PQ? println("mRecipeMap contains duplicates values") } ~~~
## Clases y métodos genéricos. (RA6.f) - Cada vez que te defines una `Collection` hay que definir dos tipos - El tipo de la `Collection` - El tipo del Elemento. Definido entre < y > ~~~ val x: MutableList <String> ~~~ - Con esto conseguimos que nuestro código sea código seguro. - Investiga sobre los tipos genéricos en la siguiente actividad. ![left](images/link.png) [Actividad ](https://github.com/revilofe/IESRA-DAM-Prog/blob/master/ejercicios/src/main/kotlin/un4/eje4_4/Generics.md)
## Iteradores. (RA6.d) Iteradores sobre elementos de una lista, set, map. - Investiga sobre los iteradores en la siguiente actividad. ![left](images/link.png) [Actividad ](https://github.com/revilofe/IESRA-DAM-Prog/blob/master/ejercicios/src/main/kotlin/un4/eje4_4/Generics.md)
## BIBLIOGRAFÍA - ![left](images/link.png) [https://kotlinlang.org/](https://kotlinlang.org) - ![left](images/link.png) [API de Array](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/) - ![left](images/link.png) [Array en kotlin](https://zetcode.com/kotlin/arrays/) - ![left](images/link.png) [Collections en kotlin oficial](https://kotlinlang.org/docs/collections-overview.html) - ![left](images/link.png) [Collections en Kotlin] (https://chercher.tech/kotlin/collections-kotlin) - Head First Kotlin, A Brain-Friendly Guide; Dawn Griffiths & David Griffiths; 2019 - O'Reilly Media
# Unidad 5 ## Creación de estructuras de datos propias usando poo: Listas, mapas, etc
## Resultado de Aprendizaje 4 > Desarrolla programas organizados en clases analizando y aplicando los principios de la programación orientada a objetos.
## Criterios de evaluación - a) Se ha reconocido la sintaxis, estructura y componentes típicos de una clase. - b) Se han definido clases. - c) Se han definido clases. - d) Se han definido propiedades y métodos. - e) Se han creado constructores. - f) Se han desarrollado programas que instancien y utilicen objetos de las clases creadas anteriormente. - g) Se han utilizado mecanismos para controlar la visibilidad de las clases y de sus miembros. - h) Se han definido y utilizado clases heredadas. - i) Se han creado y utilizado métodos estáticos. - j) Se han definido y utilizado interfaces. - k) Se han creado y utilizado conjuntos y librerías de clases.
## Contenidos mínimos: **Desarrollo de clases:** - Concepto de clase y objeto. - Estructura y miembros de una clase. Diagramas de clase. - Creación de atributos. - Creación de métodos. - Creación de constructores. - Utilización de clases y objetos. - Concepto de herencia. Tipos. Utilización de clases heredadas. - Librerías de clases. Creación. Inclusión y uso de la interface.
*********************
## Herencia. (RA4.h) ![left](images/link.png) [https://kotlinlang.org/](https://github.com/revilofe/apuntes-kotlin#herencia) - La herencia es fundamental para la programación orientada a objetos. - Nos permite crear nuevas clases que reutilizan, amplían y/o modifican el comportamiento de los preexistentes. - La clase preexistente se llama **superclase** (o clase base), y la clase nueva que estamos creando se llama **subclase** (o clase derivada). - Una subclase obtendrá implícitamente todos los campos, propiedades y métodos de la superclase (y de la superclase de la superclase si es el caso). - Hay una restricción en cuanto a cuántas clases podemos heredar; en una JVM, solo puede tener una clase base. Pero se puede heredar de múltiples interfaces.
## Herencia. (RA4.h) - La herencia es transitiva. Si la clase C se deriva de la clase B y esa clase B se deriva de una clase A dada, entonces la clase C es una clase derivada de A. - Todas las clases en Kotlin tienen una superclase común `Any`, que es la superclase predeterminada para una clase sin supertipos declarados. - Esta clase `Any` tiene unos pocos métodos básicos como `equals()` o `toString()` - ***Actividad:*** ¿Qué métodos y propiedades hereda `Example` de `Any`? ~~~Kt // Hereda de 'Any' implícitamente class Example ~~~
## Herencia. (RA4.h) - Para declarar que una clase hereda de una clase base, colocamos el tipo de la clase base después de **dos puntos** en el encabezado de la subclase. - Por defecto en Kotlin las clases están cerradas a la herencia, es decir, son `final`. - Para permitir que una clase sea heredada, hay que utilizar la palabra clave `open` - Si la clase derivada tiene un constructor primario, la clase base puede (y debe) inicializarse allí mismo, utilizando los parámetros del constructor primario. - ***Actividad:*** ¿create una variable de clase `Base`? ¿Puedes asignarle una instancia de `DerivedWithConstructor`? ~~~Kt open class Base(var p: Int) // la clase derivada tiene un constructor primario class DerivedWithConstructor(p: Int) : Base(p) ~~~
## Herencia. (RA4.h) - Si la clase no tiene un constructor primario, entonces cada constructor secundario tiene que inicializar el tipo base usando la palabra clave `super`, o delegar a otro constructor que haga eso. - Tenga en cuenta que en este caso, diferentes constructores secundarios pueden llamar a diferentes constructores de la clase base: - ***Actividad:*** Ejecuta el código siguiente. Crea el main, instancia la subclase con 1 e imprime el valor de `p` ¿Que muestra en pantalla? ¿Que sucede si quitas el constructor de la subclase? ¿Podemos definir la subclase de otra forma? ¿Que tenemos que hacer para llamar al constructor de 2 parámetros? ~~~Kt open class Base(var p: Int) { constructor(p: Int, q: Int): this(p) } class DerivedWithoutConstructor : Base { // llamando al constructor base con super() desde constructor secundario constructor(p: Int) : super(p) } ~~~
## Sobreescribir métodos - Kotlin requiere anotaciones explícitas para la sobreescritura de funciones miembro. - Para que una función pueda ser sobreescrita se utiliza la palabra clave `open` delante del nombre del método. - Dado que las clases son finales en Kotlin, sólo podemos utilizar la palabra clave `open` en métodos de instancia de clases que también hayan sido definidas como `open`. - Para indicar que una función en la clase derivada sobreescribe una función de la clase padre se utiliza la palabra clave `override` delante del nombre del método. - De esta forma le indicamos al compilador que este método sobreescribe un método de la clase padre y puede realizar las comprobaciones en tiempo de compilación.
## Sobreescribir métodos - Un método con la palabra clave `override` también es `open` por definición y puede ser sobreescrita por las subclases sucesivas. - Es posible marcar una función `override` con la palabra clave `final` para evitar que sea sobreescrita. - ***Actividad:*** Ejecuta el código siguiente. Crea el main, instancia la base y derivada y llama a todos los mètodos. ¿Que muestra en pantalla? ¿Que sucede si intentas sobre escribir el método nv? ¿Que sucede si intentas sobre escribir el método `x` de `Derived` en una nueva clase `Derived2`? Crea una nueva clase `Derived2` que sobreescriba el método `v`, imprimiendo `Derivada2`. ~~~Kt open class Base { open fun v() { println("base") } open fun x(p: Int) { println(p) } fun nv() { println(this.toString() + ": sin sobreescribir") } } class Derived: Base() { override fun v() { println("derivada") } // Restringir la sobreescritura final override fun x(p: Int) { println(p+1) } } ~~~
## Sobreescribir métodos - En Kotlin, la herencia está regulada por la siguiente regla: - Si una clase hereda varias implementaciones del mismo miembro de sus superclases inmediatas, debe invalidar este miembro y proporcionar su propia implementación. - Para denotar el supertipo del cual se toma la implementación heredada, usamos la palaba clave `super` calificado por el nombre de supertipo entre paréntesis angulares, por ejemplo, `super<Base>`.
## Sobreescribir métodos - ***Actividad:*** Ejecuta el código siguiente. Crea el main, instancia la subclase ¿Que muestra en pantalla? ¿Que muestra en pantalla si me declaro lo siguiente `var a: A = C(); a.f()` y `var b: B = C(); b.f()`? ¿Si instancias `A` y lo asignas a `a`, llamando a `a.f()`, que diferencias encuentras con la anterior llamada a `a.f()`? ~~~Kt open class A { open fun f() { print("A") } fun a() { print("a") } } interface B { fun f() { print("B") } // Los miembros de las interfaces son `open` por defecto. fun b() { print("b") } } class C() : A(), B { // El compilador requiere que 'f()' sea sobreescrito para eliminar la ambigüedad override fun f() { super<A>.f() // call to A.f() super<B>.f() // call to B.f() } } ~~~
## Sobreescribir propiedades - La sobreescritura de propiedades funciona de manera similar a la sobreescritura de métodos. - La propiedades que pueden ser sobreescritas tienen que tener la palabra `open` en su definición. - Las propiedades declaradas en una superclase que luego se vuelven a declarar en una subclase deben ir precedidas por la palabra clave `override` y deben tener un tipo compatible. - También se puede usar la palabra clave `override` como parte de la declaración de una propiedad en un constructor primario. - Cada propiedad declarada puede ser sobreescrita por una propiedad con un inicializador o por una propiedad con un método `getter()`.
## Sobreescribir propiedades - ***Actividad:*** Ejecuta el código siguiente. Crea el main, crea un objeto de `Foo` e imprime por pantalla su valor `x`. Create objetos de las subclases ¿Que diferencias ves en pantalla? ~~~kt open class Foo { open val x: String get() { return "base" } } class Bar : Foo() { override val x: String = "subclase" } interface Foo1 { val count: Int } class Bar1(override val count: Int) : Foo1 ~~~
## Orden de inicialización - Durante la construcción de una nueva instancia de una clase derivada, la inicialización de la clase base se realiza como primer paso (precedida solo por la evaluación de los argumentos para el constructor de la clase base) y, por lo tanto, ocurre antes de que se ejecute la lógica de inicialización de la clase derivada. - Por lo tanto: - Durante la inicialización de las propiedades de la clase base, las propiedades de la clase derivada aún no se han inicializado. - Si alguna de esas propiedades se utilizan (de forma directa o indirecta) en la inicialización de la clase base se pueden producir comportamientos extraños o errores en tiempo de ejecución.
## Orden de inicialización - ***Actividad:*** Ejecuta el codigo siguiente. Crea el main y instancia la clase base. ¿Cual es el orden? ~~~Kt open class Base(val name: String) { init { println("Initializing Base")} open val size: Int = name.length.also { println("Initializing size in Base: $it") } } class Derived(name: String, val lastName: String) : Base(name.capitalize().also { println("Argument for Base:$it") }) { init { println("Initializing Derived")} override val size: Int = (super.size + lastName.length).also { println("Initializing size in Derived: $it") } } ~~~
## Orden de inicialización - Durante la construcción de una nueva instancia de una clase derivada, la inicialización de la clase base se realiza como primer paso (precedida solo por la evaluación de los argumentos para el constructor de la clase base) y, por lo tanto, ocurre antes de que se ejecute la lógica de inicialización de la clase derivada. - Por lo tanto: - Durante la inicialización de las propiedades de la clase base, las propiedades de la clase derivada aún no se han inicializado. - Si alguna de esas propiedades se utilizan (de forma directa o indirecta) en la inicialización de la clase base se pueden producir comportamientos extraños o errores en tiempo de ejecución.
## Interfaces. (RA4.j) - Las interfaces en Kotlin son muy similares. - Pueden contener declaraciones de **métodos abstractos**, así como implementaciones de métodos. - Lo que los diferencia de las **clases abstractas** es que las interfaces no pueden almacenar el estado, es decir, no pueden tener variables de instancia. - Pueden tener propiedades, pero estas deben ser abstractas o proporcionar implementaciones de accesores. - Una interfaz se define usando la palabra clave `interface`. - Un método en una interfaz es abstracto por defecto si no se proporciona una implementación. - ***Actividad:*** Create la interface. Create una instancia de la interface MyInterface ¿Que sucede? ~~~Kt interface MyInterface { fun bar(): String // abstract por defecto fun foo() = 1 + 1 //Cuerpo opcional } ~~~
## Interfaces. (RA4.j) - Una clase u objeto pueden implementar una o varias interfaces: - ***Actividad:*** Create una clase `Child` que implemente la interface `MyInterface`. Create una variable e instánciala con un objeto de la clase `Child`. ¿Que sucede si no sobreescribes el método `bar`? ¿y con `foo`, puedes llamar al método `foo`? ~~~Kt class Child : MyInterface { } ~~~
## Interfaces. (RA4.j) - En una interfaz se pueden declarar propiedades. - Una propiedad declarada en una interfaz puede ser abstracta o puede proporcionar implementaciones para el `getter()` o `setter()`. - Las propiedades declaradas en interfaces no pueden tener `backing fields` y, por lo tanto, los accesores declarados en interfaces no pueden hacer referencia a ellos. - ***Actividad:*** Create una clase `Child` vacía que implemente la interface `MyInterface`, sin sobreescribir `prop`. ¿Qué sucede si intentas instanciar la clase `Child`? ~~~Kt interface MyInterface { val prop: Int // abstract val propertyWithImplementation: String get() = "foo" fun foo() { print(prop) } } class Child : MyInterface { } ~~~
## Interfaces. (RA4.j) - Una interfaz puede derivar de otras interfaces y, por lo tanto, proporcionar implementaciones para sus miembros y declarar nuevas funciones y propiedades. - Naturalmente, las clases que implementen dicha interfaz solo tienen que definir las implementaciones que faltan: - ***Actividad:*** Copia el código, create la propiedad `name2` en la interface `Named` y sobreescribe `name2` asi `override val name2: String` en la interface `Person`. Create un objeto de la clase `Employee` ¿Compila? ¿Qué sucede? ~~~Kt interface Named { val name: String } interface Person : Named { val firstName: String val lastName: String override val name: String get() = "$firstName $lastName" } data class Employee( // implementing 'name' is not required override val firstName: String, override val lastName: String, val position: Position ): Person ~~~
## Interfaces. (RA4.j) - En el caso de clases que hereden de varias interfaces, para evitar ambigüedades la subclase deberá proporcionar implementaciones tanto para métodos que tienen una implementación en una de las interfaces como en métodos que tiene implementaciones en varias interfaces. - ***Actividad:*** Modifica el método `foo` en la clase `D` para que llame también a `foo` de `B` ~~~Kt interface A { fun foo() { print("A") } fun bar() // abstract } interface B { fun foo() { print("B") } fun bar() { print("bar") } } class C : A { override fun bar() { print("bar") } } // la clase 'D' tiene que implementar tanto foo() como bar() class D : A, B { override fun foo() { super<A>.foo() } override fun bar() { super<B>.bar() } } ~~~
## Visibilidad. (RA4.g) - Modificadores de visibilidad: - **Public** - Este es el valor predeterminado, y se puede acceder a cualquier clase, función, propiedad, interfaz u objeto que tenga este modificador desde cualquier lugar. - **Private** - Se puede acceder a una función, interfaz o clase de nivel superior que se declara como privada solo dentro del mismo archivo. - **Protected** - Solo se puede aplicar a propiedades o funciones dentro de una clase, objeto o interfaz, no se puede aplicar a funciones, clases o interfaces de nivel superior. Las propiedades o funciones con este modificador solo son accesibles dentro de la clase que lo define y cualquier subclase. - **Internal** - En un proyecto que tiene un módulo (módulo Gradle o Maven), una clase, objeto, interfaz o función especificada con este modificador dentro de ese módulo solo es accesible desde ese módulo. - Las clases, objetos, interfaces, constructores, funciones, propiedades y sus 'setters' pueden tener modificadores de visibilidad. - Los 'setters' siempre tienen la misma visibilidad que la propiedad. - Cualquier función o propiedad que se declare privada dentro de una clase, objeto o interfaz solo puede ser visible para otros miembros de esa misma clase, objeto o interfaz. - Un constructor privado debe usar la palabra clave `constructor`. Si un constructor es marcado como privado no se puede instanciar un objeto con ese constructor.
## Visibilidad. (RA4.g) - Modificadores de visibilidad: ![](images/visibilidad.png)
## Visibilidad. (RA4.g) - ***Actividad:*** Create un objeto de la clase `Car` ¿Que sucede? ~~~Kt class Car private constructor(val name: String, val plateNo: String) { // .... } ~~~
## BIBLIOGRAFÍA - ![left](images/link.png) [https://kotlinlang.org/](https://kotlinlang.org) - ![left](images/link.png) [Apuntes de kotlin](https://github.com/revilofe/_kotlin_) - ![left](images/link.png) [Herencia en kotlin](https://www.develou.com/herencia-en-kotlin/) - ![left](images/link.png) [Interfaces en kotlin](https://devexperto.com/interfaces-kotlin/) - Head First Kotlin, A Brain-Friendly Guide; Dawn Griffiths & David Griffiths; 2019 - O'Reilly Media
# Unidad 6 ## Creación de programas haciendo uso de características avanzadas de la POO: Herencia y polimorfismo
## Resultado de Aprendizaje 7 > Desarrolla programas aplicando características avanzadas de los lenguajes orientados a objetos y del entorno de programación.
## Criterios de evaluación - a) Se han identificado los conceptos de herencia, superclase y subclase. - b) Se han utilizado modificadores para bloquear y forzar la herencia de clases y métodos. - c) Se ha reconocido la incidencia de los constructores en la herencia. - d) Se han creado clases heredadas que sobrescriban la implementación de métodos de la superclase. - e) Se han diseñado y aplicado jerarquías de clases. - f) Se han probado y depurado las jerarquías de clases. - g) Se han realizado programas que implementen y utilicen jerarquías de clases. - h) Se ha comentado y documentado el código.
## Contenidos mínimos: **Utilización avanzada de clases:** - Composición de clases. - Herencia. - Superclases y subclases. - Clases y métodos abstractos y finales. - Sobreescritura de métodos. - Constructores y herencia.
*********************
## herencia, superclase, subclase. (RA7.a) > ¿Como identificamos los conceptos de herencia, superclase y subclase? - Ya vimos en que consistía la herencia, las superclases y las subclases: - ![left](images/link.png) [Herencia](https://revilofe.github.io/IESRA-DAM-Prog/#/5/5)
## herencia, superclase, subclase. (RA7.a) - Existen varias funcionalidades que se le puede dar a la herencia: 1. **Especialización (es un)**: Se crea una estructura de clases en la que una especializa a la otra `Cuadrado -> Figura` - `Figura` tiene un comportamiento básico, pero cuadrado lo especializa según sus características. 2. **Extensión (extiende funcionalidad heredada)**: Se crea estructura en la que una clase extiende el comportamiento de otra sin que sea necesariamente un concepto mas especifico `ListaSalvable -> Lista` - `Lista` tiene un comportamiento completo funcional, `ListaSalvable` lo extiende añadiendo funcionalidad adicional.
## herencia, superclase, subclase. (RA7.a) - Existen varias funcionalidades que se le puede dar a la herencia: 3. **Especificación (define interface)**: Se crea una estructura en la que la superclase especifica la interface de sus descendientes. `Texto, Linea, Figura -> ObjetoGrafico` - `ObjetoGráfico` especifica como trabajar con objetos gráficos, los descendientes pueden implementar los detalles. 4. **Construcción (Usado para construir la subbase)**: La hija puede aprovechar la padre pero no tienen conexión. `Pila -> Lista` - la clase `Lista` contribuye a crear una `Pila` a través de la herencia.
## herencia, superclase, subclase. (RA7.a) - ***Actividad individual evaluable:*** [6.1 De los 4 tipos vistos, pon ejemplo de 2](https://educacionadistancia.juntadeandalucia.es/centros/cadiz/mod/assign/view.php?id=436534)
## Clases Abstractas, Interfaces (RA7.b) > ¿Como bloqueamos o forzamos la herencia en métodos y clases? - Con las **clases abstractas** y las **interfaces** forzamos la herencia (Ten en cuenta que la "herencia" a través de la interfaces no exactamente herencia) - Con `open` abrimos una clase y un método para poder heredar de la clase y sobreescribirlo el método. - Con `final` se puede marcar un método para evitar que se sobreescriba. - Recuerda - [Forzar y bloquear la herencia en clases](https://revilofe.github.io/IESRA-DAM-Prog/#/5/7) - [Forzar y bloquear la herencia en métodos](https://revilofe.github.io/IESRA-DAM-Prog/#/5/9)
## Clases Abstractas, Interfaces (RA7.b) > ¿Como bloqueamos o forzamos la herencia en métodos y clases? - Kotlin admite **clases abstractas** al igual que Java. - Una clase abstracta es una clase con métodos marcados como abstractos y que por tanto no puede ser instanciada. - Si una clase tiene uno o varios métodos abstractos es una clase abstracta y se indica con la palabra clave `abstract`. - La subclase concreta de una clase abstracta ***deberá implementar*** todos los métodos y propiedades definidos en la clase abstracta; de lo contrario, también será considerada como una clase abstracta.
## Clases Abstractas, Interfaces (RA7.b) - Las clases abstractas pueden contener métodos con implementación por defecto como cualquier otra clase. - Las subclases de la clase abstracta pueden sobreescribir la implementación predeterminada de un método pero solo si el método tiene el modificador `open`. - Los métodos marcados como `abstract` también son `open` por defecto. - Las clases abstractas también pueden definir variables de instancia al contrario que pasa con las interfaces.
## Clases Abstractas, Interfaces (RA7.b) - Ya vimos en que consistían las interfaces - ![left](images/link.png) [Interfaces](https://revilofe.github.io/IESRA-DAM-Prog/#/5/16) - Diferencias entre `Clases Abstractas` e `Interfaces` : - Las interfaces permiten definir comportamiento compartidos, mientras que las clases establecen relación de **es un** - Las clases puedes implementar varias interfaces, mientras que solo pueden heredar de una sola clase. - Puede contener propiedades abstractas y regulares pero sin campos de respaldo (`field`) - Las clases pueden tener constructores, mientras que las interfaces no. - Todas los métodos definidos por las interfaces se pueden sobrescribir sin tener que ser marcados con `open`, mientras que en las clases no.
## Clases Abstractas, Interfaces (RA7.b) - ***Actividad:*** Hereda de `Employee` y crea una clase `Teacher`. ¿Te has visto obligad@ a sobreescribir algún método? ¿Porqué? ¿Piensa dos maneras para evitar que fullName de Teacher no se pueda sobreescribir? ~~~Kt open class Person { open fun fullName(): String { ... } } abstract class Employee (val firstName: String, val lastName: String): Person() { // Variable de instancia en una clase abstracta val propFoo: String = "bla bla" abstract fun earnings(): Double // Podemos tener métodos con implementación por defecto override fun fullName(): String { return lastName + " " + firstName; } } ~~~
## Incidencia de constructores en la herencia (RA7.c) - Ya vimos como inciden los constructores en la herencia: v
## Se ha comentado y documentado el código (h) A la hora de comentar, hay dos escuelas: - usar los comentarios para **clarificar lo que quisiste expresar con tu código** - **evitarlos al máximo** y que comentar tu código es un mal necesario que sólo denota tu falta de habilidad para no hacer código lo suficientemente claro. >¿A cuál de los dos consejos deberías hacerle caso?
## Se ha comentado y documentado el código (h) - Un sistema **sin documentación** está **incompleto** - Para tener **calidad**, necesita tener **documentación**, pero esta tiene que tener sentido: es decir, *información acerca del sistema que comunique cosas como la razón de existir de ciertos módulos, valores y funciones y cómo usarlo*. - Si tienes que modificarlo, facilitará la **comprensíón** de lo que los programadores anteriores hicieron o intentarón hacer. - Por tanto la documentación es **totalmente necesaria**, ahora, donde la ponemos: - Documentos **separados** del código suelen **olvidarse** y no se mantienen. - Ponerla lo más **cerca del código**, para eso tenemos los comentarios, **facilitará encontrarlos y mantenerlos**.
## Se ha comentado y documentado el código (h) - Puedes usar los comentarios **documentar**: - Decisiones de diseño - Explicaciones sobre la existencia, funcionamiento o razón de ser de cierta parte del código - Las interfaces y su ejemplo de uso - Efectos de usar cierto código - Partes no finalizadas o que se pueden mejorar (TODO’s)
## Se ha comentado y documentado el código (h) - Los comentarios pueden **ayudarte en el futuro** - Estarán ahi para recordarte lo que hiciste y por qué. - Seguramente tu mente haya borrado información valiosa de por qué una variable tiene un valor de inicio y no otro. - Tu yo futuro y tu equipo te agradecerán los comentarios aclaratorios de tomas de decisiones.
## Se ha comentado y documentado el código (h) - Los comentarios son una **buena herramienta de diseño**. - Existen gurus, como John Ousterhout, en “A Philosophy of Software Design” que recomienda **empezar con los comentarios antes de programar**. Pero, ¿por qué lo recomienda? - Escribir en un lenguaje humano cómo funciona algo antes de implementarlo realmente, te da la capacidad de **ver si es lógico y suficiente**, además te permite **ponerte en los zapatos del usuario** para notar deficiencias sobre todo en la interfaz. Los **comentarios de la interfaz es lo primero que deberías crear** porque te servirán de guía para avanzar con tu diseño y, sobre todo, que sea lógico y fácil de usar. - Una buena guía: si no eres capaz de crear un comentario **concreto y corto** sobre cómo funciona o por qué existe algo, lo más probable es que **tengas que re-pensar tu diseño**.
## Se ha comentado y documentado el código (h) - **El lenguaje de programación no es suficiente** para expresar todo lo necesario - Todos los lenguajes de programación están pensados para ser un subconjunto del lenguaje humano que elimine las ambigüedades, manteniendo el mayor poder expresivo posible. Esto nos lleva a sus limitantes: es **imposible**, o por lo menos impráctico, **intentar expresar todas las ideas con el código**. - En la práctica, el tiempo y los recursos para lograr algo son limitados, por lo que a veces es más conveniente y fácil para todos explicar lenguaje humano algo que intentar expresarlo con código, como los puristas afirman. - No te sientas mal si tienes que recurrir de vez en cuando a explicar la forma en que funciona algo, siempre y cuando *no sea la práctica común*. - ¿Cómo usar los comentarios para que sean valiosos? - No todos los comentarios son valiosos, hay **algunos que pueden estorbar** más de lo que ayudan, por ejemplo, los que no aportan información a lo que es obvio en el código. - Hablemos de algunas formas de **aprovecharlos lo mejor posible** para que contribuyan positivamente a aumentar la calidad del proyecto.
## Se ha comentado y documentado el código (h) - Escribe *los comentarios primero* - Una de las partes más importantes de los comentarios como documentación es que **deben ser concretos, cercanos a la realidad y que proporcionen la mayor cantidad de información útil posible**. - Para lograr esto, se tienen que **crear lo más cerca que puedas a la creación del código**. Pero como todos sabemos que después de escribir y probar (básicamente) el código vamos a sentir que ya está terminado, es buena práctica obligarte a escribirlos antes, **justo como propone TDD con las pruebas**. - De esta manera te asegurarás que tu código esté documentado incluso antes de escribirlo y **te servirán como una herramienta de diseño** que te ayudará a pensar mejor en la usabilidad de tus módulos y piezas de software.
## Se ha comentado y documentado el código (h) - **Crea** comentarios **sobre la interfaz** - **La interfaz es el medio de uso que tus módulos o funciones presentan** para que las demás partes de tu sistema lo usen. - Lo primero que deberías documentar y explicar es esta interfaz, para que más personas a parte de ti puedan usar este pedazo de código. - Debes escribir comentarios claros sobre: - -> **Cómo usar esa pieza de código** - -> **Por qué existe esa parte del sistema** - -> **Qué efectos tiene usarla** - Este tipo de comentarios son los que aportan mayor valor al sistema y si están lo suficientemente completos, con ejemplos y explicaciones claras, son una documentación válida que está en un muy buen lugar: es fácil de encontrar y no se va a perder enterrada entre otros documentes que después nadie va a consultar.
## Se ha comentado y documentado el código (h) - **Evita** los comentarios **sobre la implementación** - Los comentarios sobre la implementación son aquello que describen qué estas haciendo, como por ejemplo, sumar número, abrir un archivo, etc. - Estos comentarios normalmente **son innecesarios**, ya que lo que se está haciendo es obvio si el código es lo suficientemente expresivo y siempre deberíamos buscar que sea así. - De hecho, estos son los comentarios que hacen que la gente odie a los comentarios en general, pues **en vez de proporcionar información extra son una carga que hay que mantener y pueden confundir si no son actualizados**. - Si realmente sientes que tienes que explicar qué estás haciendo con cierta pieza de código, primero **pregúntate si no hay una manera de reescribirlo para que sea obvio**. - Si no existe o no es práctica esta solución, entonces escribe el comentario de la manera más concisa posible, incluyendo la razón de la existencia de ese código. - Para hacer esto debes tomar muy en cuenta los recursos del proyecto: **no te puedes tardar el triple del tiempo** implementando la pieza de código perfecta porque no quieres escribir un comentario que explique cómo funciona.
## Se ha comentado y documentado el código (h) > Escribir comentarios es una de las grandes tareas que los programadores debemos dominar. > Los lenguajes de programación y los entornos de programación cada vez le dan más poder a esta parte de los programas y permiten incluso escribir pruebas en ellos, generar documentación automática y listar tareas a partir de ellos. > Si pones el suficiente esmero en aprender a escribir buenos comentarios y mantenerlos, serán una gran herramienta de diseño y documentación de tu software.
## Se ha comentado y documentado el código (h) ### DOKA ![left](images/link.png) [Dokka](https://kotlin.github.io/dokka/1.6.10/) - **Herramienta que permite genera la documentación**. - Configuración básica y mínima: Añade al fichero `build.gradle.kts:` ~~~ plugins { id("org.jetbrains.dokka") version "1.6.10" } repositories { mavenCentral() } ~~~ - Ahora en aparecerán nuevas tareas en la pestaña de gradle.
## Se ha comentado y documentado el código (h) ### KDOC ![left](images/link.png) [Sintaxis de KDoc](https://kotlinlang.org/docs/kotlin-doc.html#kdoc-syntax) - **Lenguaje que permite documentar**. - Documenta la interface de las clases, métodos, propiedades, etc. - Para genera la documentación, en las opciones de `Gradle`, busca la tarea `Task->Documentación->DokkaHtml` y púlsala. - La documentación se genera en la carpeta `build` de tu proyecto.
## Se ha comentado y documentado el código (h) - *** *** [6.x Generera la documentación del programa.](https://educacionadistancia.juntadeandalucia.es/centros/cadiz/mod/assign/view.php?id=436534)
## Se ha comentado y documentado el código (h) - ***Actividad individual evaluable:*** [6.4 Comentar y documentar el código (RA7.h)](https://educacionadistancia.juntadeandalucia.es/centros/cadiz/mod/assign/view.php?id=447140)
## Se ha comentado y documentado el código (h) - ***Actividad individual evaluable:*** Investiga sobre Depedencia, Asociación, Agregación composición. - Describe que representa en el código, y para ello usa tambien un ejemplo de código - Representa el ejemplo y la relación haciendo uso de UML [Ejemplo](http://alumnosdc.blogspot.com/2013/05/agregacion-composicion-y-dependencia.html)
## Principio de inversión de dependencias (RA7.) - Básicamente lo que nos dice este principio es que: - Las clases de alto nivel no deberían depender de las clases de bajo nivel. Ambas deberían depender de las abstracciones. - Las abstracciones no deberían depender de los detalles. Los detalles deberían depender de las abstracciones.
## Principio de inversión de dependencias (RA7.) - En Informática, **Inyección de Dependencias** (en inglés Dependency Injection, DI) es un patrón de diseño orientado a objetos, en el que **se suministran objetos a una clase** en lugar de ser la propia clase quien cree el objeto. - Es una herramienta comúnmente utilizada en varios patrones de diseño orientado a objetos, consiste en inyectar comportamientos a componentes. - El término fue acuñado por primera vez por *Martin Fowler*.
## Principio de inversión de dependencias (RA7.) - Esto no es más que extraer responsabilidades a un componente para delegarlas en otro, estableciendo un mecanismo a través del cual el nuevo componente pueda ser cambiado en tiempo de ejecución. - Es conveniente no confundir **Inversión de dependencias (DIP)** con **Inversión de Control (IoC)**. - Inyección de dependencias (Patrón de diseño): Las abstraciones nunca deben depender de los detalles. - Inversión de dependencias (Principio DIP de SOLID)
## Principio de inversión de dependencias (RA7.) - Cumplir con el DIP hace que el código de la lógica de negocio de tu aplicación no dependa de los detalles de implementación, si no de abstracciones. Esto hará que en el futuro puedas cambiar los detalles de implementación sin tener que modificar el código de tu lógica de negocio. - [Ejemplo](https://github.com/revilofe/IESRA-DAM-Prog/blob/master/ejercicios/src/main/kotlin/un6/dip/dip.md)
## BIBLIOGRAFÍA - ![left](images/link.png) [https://kotlinlang.org/](https://kotlinlang.org) - ![left](images/link.png) [Apuntes de kotlin](https://github.com/revilofe/_kotlin_) - ![left](images/link.png) [Clases abstractas, interfaces, herencia] (https://code.tutsplus.com/es/tutorials/kotlin-from-scratch-abstract-classes-interfaces-inheritance-and-type-alias--cms-29744) - ![left](images/link.png) [Clases abstractas] (https://www.develou.com/clases-abstractas-en-kotlin/) - ![left](images/link.png) [Herencia en kotlin](https://www.develou.com/herencia-en-kotlin/) - ![left](images/link.png) [Interfaces en kotlin I](https://www.develou.com/interfaces-en-kotlin/) - ![left](images/link.png) [Interfaces en kotlin II](https://devexperto.com/interfaces-kotlin/) - ![left](images/link.png) [https://kotlinlang.org/](https://kotlinlang.org) - ![left](images/link.png) [Deberías comentar tu código]([)https://blog.thedojo.mx/2020/12/30/deberias-comentar-tu-codigo.html) - Head First Kotlin, A Brain-Friendly Guide; Dawn Griffiths & David Griffiths; 2019 - O'Reilly Media - A Philosophy of Software Design, John Ousterhout. (Le dedica 4 capítulos a buen uso de los comentarios)
# Unidad 7 ## Operaciones de entrada/Salida y GUI
## Resultado de Aprendizaje 5 > Realiza operaciones de E/ y S/ usando el lenguaje y librerias
## Criterios de evaluación - a) Se ha utilizado la consola para realizar operaciones de entrada y salida de información. - b) Se han aplicado formatos en la visualización de la información. - c) Se han reconocido las posibilidades de entrada/salida del lenguaje y las librerías asociadas. - d) Se han utilizado ficheros para almacenar y recuperar información. - e) Se han creado programas que utilicen diversos métodos de acceso al contenido de los ficheros. - f) Se han utilizado las herramientas del entorno de desarrollo para crear interfaces gráficos de usuario simples. - g) Se han programado controladores de eventos. - h) Se han escrito programas que utilicen interfaces gráficos para la entrada y salida de información.
## Contenidos mínimos: Información desde el sistema de archivos. 1. Fundamentos de sistema de archivos. 1.1. Archivos (Texto, Binarios) 1.2. Directorios. 1.3. Flujos de E/S (Texto, Bytes) 2. La consola y el teclado (RA5.a, b) 2.1. Escribir por consola 2.2. Lectura desde teclado 2.3. Formato a la información. (Scanner & println) 3. API para trabajar con ficheros (RA5.c) 4. Trabajar con ficheros (RA5.d, e) 4.1. Texto 4.2. Binarios
## Contenidos mínimos: Información desde interfaz gráfica de usuario 5. Elementos básicos de una interface (RA5.f) 6. Gestión de eventos (RA5.g) 6.1. Eventos 6.2. Controlador de eventos 7. Uso de GUI para E/S de información (RA5.h)
*********************
## Aplicaciones y sistema de archivos - ¿Principal función de una aplicación informática? ![center](images/programa.gif) - Trabajamos con datos, variables.... ¿Que pasa cuando se cierra la aplicación? - ¿Que nos facilita el sistema de Archivos? - ¿Que elementos puedes encontrar en un [sistema de archivos](https://es.wikipedia.org/wiki/Sistema_de_archivos)?
## Aplicaciones y sistema de archivos - La gestión del **sistema de archivos** ¿es una función del ... ? - Los lenguajes de programación también proporcionan su propia biblioteca para trabajar con el sistema de archivos - Kotlin ofrece un conjunto de clases incluidas dentro del [Package `kotlin.io`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/) - Estas clases están basadas en las ofrecidas por Java en el package `java.io`. - Mediante la invocación de los métodos adecuados definidos de estas clases es posible llevar a cabo prácticamente cualquier tarea sobre el sistema de archivos.
## Flujos En Kotlin, heredado de Java, se define la abstracción de stream (flujo) para tratar la comunicación de información entre el programa y el exterior - Entre una fuente y un destino fluye una secuencia de datos Los flujos actúan como interfaz con el dispositivo o clase asociada - Operación independiente del tipo de datos y del dispositivo - Mayor flexibilidad (p.e. redirección, combinación) - Diversidad de dispositivos (fichero, pantalla, teclado, red, …) - Diversidad de formas de comunicación - Modo de acceso: secuencial, aleatorio - Información intercambiada: binaria, caracteres, líneas ![center](images/flujo1.png)
## Flujos Como en Unix: - Entrada estándar - habitualmente el teclado - Salida estándar - habitualmente la consola - Salida de error - habitualmente la consola En Java se accede a la E/S estándar a través de campos estáticos de la clase `java.lang.System` - `System.in` implementa la entrada estándar - `System.out` implementa la salida estándar - `System.err` implementa la salida de error ![center](images/flujo2.png) Curiosidad: Mira la implementación de `println()`, `readline()`
## E/S por Consola (RA5.a, b) - ![left](images/link.png) [Lectura y escritura en entrada y salida estándar](https://github.com/revilofe/IESRA-DAM-Prog/blob/master/ejercicios/src/main/kotlin/un7/IO.md#3-lectura-y-escritura-en-entrada-y-salida-estandar) ### API: - Escribir: `print`, `println` - Leer: `readline`, `readln` - **Evita el uso de `!!`** - Haz uso de `try` y `?:` - Haz uso de `?` y `toIntOrNull` y similares - Formato: `String.Format`
## E/S por Consola (RA5.a, b) - Actividad - ***Actividad grupo evaluable:*** [7.1. Realiza el formateo de tu horario](https://educacionadistancia.juntadeandalucia.es/centros/cadiz/mod/assign/view.php?id=484879)
## API para trabajar con ficheros (RA5.c) - Clase `File` ![left](images/link.png) [Apuntes E/S en archivos - Gestión de archivos](https://github.com/revilofe/IESRA-DAM-Prog/blob/master/ejercicios/src/main/kotlin/un7/IO.md#2-gesti%C3%B3n-de-ficheros) ----- - La clases mas básica para operar con archivos es la clase `File`, ubicada en el package `java.io` de java. - habrá que importarla `import java.io.File` - Kotlin extiende `File` añadiéndole nuevos métodos para facilitar su uso, en el paquete `kotlin.io` - `File`, además, representa la **ruta de un archivo o directorio dentro del sistema de archivos**. - Esta clase permite manipular *cualquier aspecto vinculado al sistema de archivos*: - **Ficheros**: abrir, cerrar, borrar, renombrar, ... - **Directorios**: abrir, listar contenido, borrar, renombrar, ...
## API para trabajar con ficheros (RA5.c) - Clase `File` - `File` tendremos que instanciarla, y recibe como argumento una `String` que corresponde a la ruta del archivo o directorio. - La ruta, **Path** en inglés, contiene el camino o ruta donde encontrarlo, junto al nombre del archivo o directorio . - La ruta, es única en un sistema de archivos. - La ruta puede ser relativa y absoluta. ~~~Kotlin val ruta = "./data.txt" //Relativa val f = File(ruta) ~~~
## API para trabajar con ficheros (RA5.c) - Clase `File` - Sobre la ruta podemos decir: - Que dependen del sistema de archivos: Por ejemplo, Windows (`C:\` y `\`) y Linux (`/var` y `/`) - Kotlin nos permite usar `/` para representar rutas. - Un objeto `File` representa solo una ruta. Para varias rutas, habrá que crear varios objetos `File`'s ~~~Kotlin var carpetaFotos: File = File("C:/Fotos") //Absoluta var unaFoto: File = File("C:/Fotos/Foto1.png") var otraFoto: File = File("C:/Fotos/Foto2.png") ~~~
## API para trabajar con ficheros (RA5.c) - Clase `File`, Ejemplo - ***Actividad individual:*** Accede al ejemplo, ejecutalo y investiga y actúa para que el programa responda `true` a la pregunta ¿Existe? y ¿archivo? ¿carpeta?. [Ejemplo1](https://github.com/revilofe/IESRA-DAM-Prog/blob/master/ejercicios/src/main/kotlin/un7/E01ExisteYTipo.kt) - ¿Usarás ruta relativa o absoluta? - ¿En que SO trabajas? - ¿Te ha funcionado?, ¿que has tenido que modificar? - ¿Te has fijado en los métodos que se utilizan?
## API para trabajar con ficheros (RA5.c) - Tipos de rutas - Conceptos: - **Raíz**: Punto de inicio de la estructura de archivos. La Raíz depende del sistema operativo. - **Directorio de trabajo**: Directorio que se asigna a un programa cuando se ejecuta, normalmente el directorio en el que esta el ejecutable. *¿Cual es el directorio de trabajo de nuestro IDE, cuando ejecutamos un proyecto?* - Rutas relativas y absolutas - **Absoluta**: Referencia de un objeto desde la raíz. - **Relativa**: Referencia a un objeto desde el directorio de trabajo. El directorio de trabajo puede cambiar cada vez que se ejecuta el programa. *¿Cuando usar una y cuando usar otra?*
## API para trabajar con ficheros (RA5.c) - Tipos de rutas - La ruta relativa - Es similar a la absoluta, pero nunca se indica la raíz. - Incluye la raíz a pesar de NO indicarse. - Permite la portabilidad del software. Por ejemplo: ```kotlin val f = File("Unidad11/apartado1/Actividades.txt") ``` Dependiendo del directorio de trabajo sería: | Directorio de trabajo | Ruta real | | :--------------------------: | :-------------------------------------------------------: | | `C:/Proyectos/Java` | `C:/Proyectos/Java/Unidad11/apartado1/Actividades.txt` | | `X:/Unidades` | `X:/Unidades/Unidad11/apartado1/Actividades.txt` | | `/Programas` | `/Programas/Unidad11/apartado1/Actividades.txt` |
## API para trabajar con ficheros (RA5.c) - Tipos de rutas, Ejemplo - ***Actividad individual:*** Accede al ejemplo, ejecutalo y investiga y actúa para que el programa muestre información de las dos rutas relativas y absolutas. [Ejemplo 2](https://github.com/revilofe/IESRA-DAM-Prog/blob/master/ejercicios/src/main/kotlin/un7/E02RutaRelativaAbsoluta.kt) - ¿Te ha funcionado?, ¿que has tenido que modificar? - ¿Identificas ahora el directorio de trabajo del IDE? - ¿Te has fijado en los métodos que se utilizan?
## API para trabajar con ficheros (RA5.c) - API `File` - URLs de consulta: - [File Java 17](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/File.html) - [File Kotlin](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-file/)
## API para trabajar con ficheros (RA5.c) - API `File` - `File`: **Obtener la ruta** - `getParent`: devuelve la ruta de la carpeta del elemento referido por esta ruta. - `getName`: devuelve el nombre del elemento que representa en la ruta. - `getAbosultePath`: devuelve la ruta absoluta. [Ver Ejemplo 2](https://github.com/revilofe/IESRA-DAM-Prog/blob/master/ejercicios/src/main/kotlin/un7/E02RutaRelativaAbsoluta.kt) - ¿Detectas algo extraño en el nombre de los métodos? - Recuerda que en kotlin, los métodos `getX` y `setX` se llaman automáticamente, al acceder y establecer valor a la propiedad.
## API para trabajar con ficheros (RA5.c) - API `File` - `File`: **Comprobaciones de estado** - `exists`: comprueba si la ruta existe dentro del sistema de ficheros. - `isFile`: comprueba el sistema de ficheros en busca de la ruta y devuelve true si existe y es un fichero. - `isDirectory`: funciona como el anterior pero comprueba si es una carpeta [Ver Ejemplo1](https://github.com/revilofe/IESRA-DAM-Prog/blob/master/ejercicios/src/main/kotlin/un7/E01ExisteYTipo.kt) - ¿Detectas algún método mas de `File` que de información sobre el estado del fichero o directorio? `isHidden()`
## API para trabajar con ficheros (RA5.c) - API `File` - `File`: **Propiedades de ficheros** - `length`: devuelve el tamaño de un archivo en bytes. - `lastModified`: devuelve la última fecha de edición del elemento representado por esta ruta.
## API para trabajar con ficheros (RA5.c) - API `File`, Ejemplo - ***Actividad individual:*** Accede al ejemplo, ejecutalo y investiga y actúa para que el programa muestre información distinta a la primera ejecución. [Ejemplo3](https://github.com/revilofe/IESRA-DAM-Prog/blob/master/ejercicios/src/main/kotlin/un7/E03PropiedadesFicheroYDirectorios.kt) - ¿Detectas algún método mas de `File` que de información sobre propiedades del fichero o directorio? `canWrite()`, `canRead()` - ¿Te ha funcionado?, ¿que has tenido que modificar? - Cambia el fichero y vuelve a ejecutarlo. ¿Han cambiado los valores?
## API para trabajar con ficheros (RA5.c) - API `File` - `File`: **Gestión de ficheros** - `mkdir`: permite crear una carpeta, indicando la ruta junto con el nombre de la carperta - `delete`: borra el archivo o carpeta. Se podrá borrar una carpeta si está vacía.
## API para trabajar con ficheros (RA5.c) - API `File`, Ejemplo - ***Actividad individual:*** Para probar el ejemplo primero asegúrate de que en el Directorio de Trabajo no hay ninguna carpeta llamada `Temp` y ejecute el programa. Todo fallará, ya que las rutas son incorrectas (no existe `Temp`). Luego, crea la carpeta `Temp` y en su interior crea un nuevo documento llamado `Documento.txt` (puede estar vacío). Ejecuta el programa y verás que se habrá creado una nueva carpeta llamada `Fotos`. Si lo vuelves a ejecutar por tercera vez podrás comprobar que se habrá borrado. [Ejemplo4](https://github.com/revilofe/IESRA-DAM-Prog/blob/master/ejercicios/src/main/kotlin/un7/E04CreaBorraDirectorios.kt) - ¿Te ha funcionado?, ¿que has tenido que modificar? - ¿Entiendes la lógica del ejemplo?
## API para trabajar con ficheros (RA5.c) - API `File` - `File`: **Gestión de ficheros** - `renameTo`: permite cambiar el nombre y ubicación de un archivo o directorio.
## API para trabajar con ficheros (RA5.c) - API `File`, Ejemplo - ***Actividad individual:*** Dentro de la carpeta `Temp` crea una carpeta llamada `Media` y otra llamada `Fotos`. Dentro de la carpeta `Fotos` crea dos documentos llamados `Documento.txt` y `Fotos.txt`. Después de ejecutar el programa, observa como la carpeta `Fotos` se ha movido y ha cambiado de nombre, pero mantiene en su interior el archivo `Fotos.txt`. El archivo `Documento.txt` se ha movido hasta la carpeta `Temp`. [Ejemplo5](https://github.com/revilofe/IESRA-DAM-Prog/blob/master/ejercicios/src/main/kotlin/un7/E05RenombraFicheroYDirectorios.kt) - ¿Te ha funcionado?, ¿que has tenido que modificar? - ¿Entiendes la lógica del ejemplo?
## API para trabajar con ficheros (RA5.c) - API `File` - `File`: **Listar contenido de directorio** - `listFiles`: vector de objectos `File` con todos los elementos contenidos en la carpeta.
## API para trabajar con ficheros (RA5.c) - API `File`, Ejemplo - ***Actividad individual:*** Antes de ejecutarlo, crea una carpeta `Temp`. Dentro crea o copia cualquier cantidad de carpetas o archivos. [Ejemplo6](https://github.com/revilofe/IESRA-DAM-Prog/blob/master/ejercicios/src/main/kotlin/un7/E06ListaContenidoDirectorio.kt) - ¿Te ha funcionado?, ¿que has tenido que modificar? - ¿Entiendes la lógica del ejemplo?
## API para trabajar con ficheros (RA5.c) - Actividad - ***Actividad individual evaluable:*** [7.2. Realiza una tabla resumen con los método mas importantes de `File`](https://educacionadistancia.juntadeandalucia.es/centros/cadiz/mod/assign/view.php?id=484897)
## E/S por Consola (RA5.c) - Actividad - ***Actividad grupo evaluable:*** Piensas los cambios que harías en el programa, para que la lectura del horario se realice a través de un fichero. [7.1. Realiza el formateo de tu horario](https://educacionadistancia.juntadeandalucia.es/centros/cadiz/mod/assign/view.php?id=484879)
## BIBLIOGRAFÍA - ![left](images/link.png) [https://kotlinlang.org/](https://kotlinlang.org) - ![left](images/link.png) [https://www.fdi.ucm.es/profesor/jpavon/poo/2.13.EntradaySalida.pdf](https://www.fdi.ucm.es/profesor/jpavon/poo/2.13.EntradaySalida.pdf) - ![left](images/link.png) [Apuntes de kotlin](https://github.com/revilofe/_kotlin_) - ![left](images/link.png) [Apuntes E/S en ficheros](https://github.com/revilofe/IESRA-DAM-Prog/blob/master/ejercicios/src/main/kotlin/un7/IO.md)
## Unidad 8
Bloques de diapositivas
## Unidad 9
Bloques de diapositivas