0% encontró este documento útil (0 votos)
78 vistas

Scala

Este documento describe las estructuras de control de bucles (while, do while y for), funciones y condiciones booleanas en Scala. Explica cómo se definen funciones y cómo se pueden anidar funciones dentro de otras. También cubre el patrón matching para reconocimiento de patrones, y cómo trabajar con colecciones mediante funciones como map y foreach. Por último, introduce conceptos de herencia y polimorfismo mediante la definición de clases.
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como RTF, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
78 vistas

Scala

Este documento describe las estructuras de control de bucles (while, do while y for), funciones y condiciones booleanas en Scala. Explica cómo se definen funciones y cómo se pueden anidar funciones dentro de otras. También cubre el patrón matching para reconocimiento de patrones, y cómo trabajar con colecciones mediante funciones como map y foreach. Por último, introduce conceptos de herencia y polimorfismo mediante la definición de clases.
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como RTF, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 29

SCALA

BUCLES
Las 3 estructuras de control de bucles principales que tenemos en Scala (while, do while y for):

var nombreVar = 10

while (x>=10){

println(x)

x-=1

do {

println(x)

x-=1

}while (x>=10)

La difernecia entre while y do es que do al menos se ejecuta siempre una vez, se cumpla o no
la condición.

En el caso de los bucles for hay que indicarle el x, la condición de parada y el incrementador o
el reductor. En Scala esas instrucciones separadas dentro del for se especifican así:

for (x <- 10 to 0 by -1) {

println(x)

Aquí vamos de 10 a 0, decrementando en 1 en cada vuelta.

for (y <- 0 until 10) {


println(y)

Aquí hemos puesto que y vaya de 0 a 10, genera una lista de 10 elementos que no llega a 10,
sino que va de 0 a 9.

for (y <- 0 to 10) {

println(y)

Si cambiamos until por to llegamos a 10, llega de 0 a 10, genera una lista de 100 elementos. La
diferencia es la palabra clave, until no incluye el último elemento, el último valor, pero to sí.
Podemos generar listas incluyendo el último valor o excluyéndolo.

Configuramos el worksheet para que sea interactivo, de lo contrario cada vez que realicemos
un salto de línea habrá que hacer click sobre el botón de play. Check en interactive mode

FUNCIONES CONDICIONES

Cómo podemos definir funciones y cómo podemos usarlas.

Creamos un nuevo Scala Worksheet. Comenzamos a definir la función con def

def Nombrefuncion(s”parámetro : tipo, parámetro : tipo”): TipoRetorno


Unit viene a ser el void de Java.

Para llamar a la función:

printName(name= carlos, surname= el de los cojones largos)

Podemos definir otra sintaxis de funciones asignándosela a una variable:

val triple = (i: Int) =>i*3

println(triple(3))

Triple es una variable que almacena una función que recibe un parámetro de tipo entero y
devuelve su valor triplicado. Triple está siendo llamado y ejecutando la función que almacena.

Si escribimos una lista:

var l = List(1, 2, 3, 4)

Las colecciones tienen funciones de primer orden (funciones que aceptan funciones, esta es
una de las características del lenguaje funcional por la cual scala es muy potente), podemos
acceder a ellas recurriendo a map

l.map(x => triple(x))

Así se aplicará a cada uno de los elementos la función triple, la variable x definida tomará cada
uno de los valores de la lista (x será 1, será 2, será 3 y será 4) y a x se le aplicará triple. L está
defnida como un val, con lo cual es inmutable, con lo cual map se aplicará a cada uno de los
elementos la función triple y generará una nueva lista que devolverá sus valores

No existe ninguna variable que reciba la referencia a la respuesta que está dando map así que
el compilador ha decidido darle uno, que es res2. Rest2 es una lista de enteros que contiene
los valores devueltos de aplciar triple a la lista l

Las interacciones en las colecciones en scala no es como en java con un bucle, en python
también tienen map pero funciona de forma diferente a la de scala. Las iteraciones en las
colecciones son más ágiles y funcionales que en otros lenguajes de programación.

Otra sintaxis válida para aplicar la función sería a map pasarle directamente la función con un
underscore (_), indicándole al compilador que se va a aplicar la función triple a cada uno de los
elementos de map, para indicar ''a cada uno de los elementos'' usamos el underscore, es una
variable anónima, que no almacena referencia a ella, pero se va a usar

Map es una función de orden superior o de primer orden que acepta triple como parámetro. El
resultado que obtendremos será el mismo.

CONDICIONES BOOLEANAS

También pueden ser introducidas como parámero a map.

Si x es par, ejecutamos triple(x)


Devuelve una lista de Anyval, debido a que sólo hemos puesto una parte de la condición, ¿qué
pasa cuando no se cumple?, es por eso que marca los espacios de la lista con (), que viene a
indicar cualquier valor, un option. Para solventarlo añadimos lo que ocurre cuando no se
cumple la condición, el else.

Cuando no se cumple, no se cambia el valor. Esto nos aporta mucha versatilidad a la hora de
aplicar funciones o iterar sobre las listas.
FUNCIONES ANIDADAS

Ejemplo. Función1 que reciba un entero y devuelva un entero también. Dentro de esta función
definimos otra función que reciba también un entero que nos devolverá un int también.

En el cuerpo de la Función1 vamos a hacer la llamada a suma. Estamos llamando aquí a los
parámetros nombrados, si los parámetros están nombrados no tienen por qué ir en el mismo
orden, sabrá interpretarlo correctamente. Y ya devovlemos el valor que devuelva suma.

En las funciones no hace falta poner la palabra clave Return, ya que la última línea el
compilador la toma como valor de retorno. En este caso suma es de tipo entero y al llamar a
suma va a devolver un entero, con lo cual funcion1 va a devolver un entero y no hay fallo en la
compilación

Suma está definida dentro de función1, si la intentamos llamar desde fuera nos dará un error,
no está definida, porque sólo está dentro del scope de funcion1, es accesible sólo desde dentro
del cuerpo de funcion1

PATRONES
Patter matching, reconocimiento de patrones

Es una de las aplicaciones principales de Scala. En Scala se pueden matchear tipos, clases, a
diferencia de Java, lo que lo hace más potente que el Switch de Java.
Creamos un nuevo paquete, sobre la carpeta scala > New > package
Y un nuevo worksheet.

Definimos una función que reciba como parámetro un carácter y nos de su nombre en griego, y
que para el resto de casos no contemplados que devuelva "no reconocido":

def nombreFuncion (parametro : tipoparametro) {

Si llamamos a esta función nos devolverá el equivalente.

Matchea la letra con cada uno de los case expuestos. Como no lo estamos asignando a ninguna variable nos
devuelve res0 = alpha

Si insertamos una condición no contemplada (definida en el _), nos devolverá "no reconocido"

También podemos definir una función que nos devuelva el mayor de dos valores introducidos. Ponemos un
reconocimiento de patrones en el que a > b y matchee si es true, el mayor será a, si es false, será b.

El compilador es capaz de ver el valor que estamos devolviendo y definir el tipo de max sin necesidad de definirlo.
Nos devuelve 10

También podemos hacer pattern matching con clases. Comenzamos definiendo una jerarquía de clases simple.

La clase B tiene un parámetro de tipo entero que extiende de A, C tendrá como parámetro un string y extiende de
A. Definimos una función sencilla que recibe un parámetro de tipo A = param match

matchCases es una función que recibe un parámetro de tipo A, del cual heredan B y C. Y B y C son dos case clases,
en el cual la primera B que recibe un parámetro a de tipo entero, y la segunda clase es B que tiene un atributo B de
tipo String.

Definimos dos variables que tienen una instancia de B y de C respectivamente. Si llamamos a esta función y le
pasamos la variable como parámetro

B y C extienden el trait A, y aquí estamos matcheando, si es el tipo B, devuelve "es B y su contenido es X"; mientras
que si es C devuelve "es C y su contenido es X"

Es decir, podemos hacer matcheado de tipos, comprobar que coincidan los tipos. En Java habría que hacer una
función que es isIntanceOf, que muchas veces no resuelve correctamente los tipos sobre todo cuando hay
herencias jerárquicas etc.

MAP FOREACH COLECCIONES

Vamos a ver las colecciones de Scala y cómo trabajar con ellas.

Sobre scala > New > Package


Y haciendo click sobre este creamos el worksheet.

Definimos una variable frutas .


Tanto en Python como en Java, usaríamos un bucle for para imprimir los valores de frutas por pantalla.

Scala provee de una serie de funciones y utilidades para interactuar con las colecciones, todas son funciones de
orden superior, es decir, que aceptan otras funciones, y se aplican las funciones que reciben en los elementos de
esta colección.

En la firma de la función la función foreach es una función genérica, que recibe un parámetro de tipo, que se podría
establecer, pero en este caso lo va a saber inferior, porque sabe fruta es una colección de string, es un set de string,
y devuelve una instancia del parámetro del tipo que haya recibido foreach.

Mientras que en otros lenguajes tendríamos que definir for x in frutas... en java tenemos las funciones de
iteracción, de orden superior, que permiten usar otras funciones y aplicarlas.

Otro ejemplo, con map hacemos que para todos los casos los convierta a mayúsculas.

Podemos concatenar funciones, de tal forma que a la colección que nos devuelve map le apliquemos foreach para
que nos lo imprima por pantalla

Map NO muta la colección inicial frutas, si la imprimimos vemos que está intacta. Por tanto la mejor manera de
manipular las colecciones es recurriendo a las funciones de orden superior definidas en Scala.

Vamos a definir un MAP, que se define con tuplas.


Podemos usar las mismas funciones, vamos a generar un nuevo mapa con una secuencia más y posteriormente
pasarlo a mayúsculas todo. Estamos exigiendo que sea un matcheo, por tuplas para cada elemento del map,
tenemos que añadir {} porque si usamos () implicamos que vamos a llamar a una función directamente, no
indicarle instrucciones

Le estamos diciendo que a map se le aplique la instrucción de la línea del case: un case donde va a matchear el
primer elemento como pais y el segundo como capital, y vamos a devolver ambos elementos pero
transformándolos en mayúscula.

Esto genera un nuevo map.

HERENCIA Y POLIMORFISMO

Creamos un nuevo package y un nuevo worksheet.


Creamos una clase Persona

Que tiene dos atributos, edad y nombre. Y define 3 funciones: la primera está sobreescribiendo la clase toString de
Java, define la función prettyPlint, sin implementarla, y birthday, que sí implementa, que es un Unit que va
actualizando la edad.

Definimos la clase Employee, que tiene 3 atributos, y extiende o hereda de Person y la especifica con nombre y
edad.
Y definimos la clase Graduate, con 4 atributos, hereda de Person, la cual se va a instanciar pasándole la n de
nombre y a de edad.

COLECCIONES
Scala ofrece distintos tipos de colecciones: tuplas, arrays, listas, secuencias,
conjuntos y mapas

COLECCIONES TUPLAS

Estructura de datos que almacena un nº fijo de elementos. Cada uno de ellos puede ser de distinto tipo.

Las definimos entre () separadas por comas

Así por ejemplo la variable t es una tupla cuyo primer elemento es un string y el segundo un entero.

Para acceder a los elementos de una tupla lo hacemos a través de la posición, los índices, precedidos por un _
La primera posición empieza con el 1
También podemos generar, si tenemos almacenada la referencia de cada una de las posiciones de la tupla
(almacenada en una variable), a partir de estas variables, una nueva tupla

La tupla puede almacenar un nº finito de elementos hasta 22. Es el número máximo de elementos que puede
aceptar una tupla.

COLECCIONES ARRAYS

Para generar un array recurrimos a Array() y separamos los elementos por comas. Todos los elementos del array
deben ser del mismo tipo.

Con la opción zip podemos generar un array de tuplas.

La variable simbolos es un array, tiene disponible la función zip, que toma como parámetro una colección iterable,
un array es una colección iterable, al cual si le pasamos otro array generará una tupla emparejando los elementos
de ambas listas por posición.

Nos genera un array de 3 tuplas, emparejando ambos elementos de los arrays simbolos y numeros.
:
Si almacenamos el resultado de zip en otra variable y recorremos cada elemento con un bucle for nos imprime las 3
tuplas

La funcion dividePor10 toma un entero y devuelve una tupla de enteros, que será la divisón entera de n/10 (n es el
parámetro de entrada de la función) y el segundo valor en la entrada de la tupla será el resto, el módulo.

La función sólo tiene una única expresión a evaluar así que no hace falta meter el cuerpo de la función entre llaves.

Podemos hacerlo de otra forma:

Para recorrer un array usamos el bucle for.

COLECCIONES LIST

Para construir una lista usamos la palabra reservada List() y separamos los elementos por comas.
También podemos usar el operador :: en conjunción de la palabra reservada Nil, que indica el fin de la lista
O podemos usar la función range de List en el que indicamos un inicio y un final de lista. Así podemos crear una
lista autogenerada que va desde el primer elemento hasta el segundo.
Las listas también pueden contener tuplas:

Calcular la suma de los elementos de una lista con un bucle for:

Recorremos cada una de las posiciones de la lista y lo acumulamos en la vv sum.

También podemos hacer esto recurriendo a funciones de orden superior que están disponibles en todas las
colecciones de Scala como foreach. Foreach toma una sentencia o función a ejecutar como parámetro,

Tras ejecutar el foreach mostramos sum, y dará igual, 15.

COLECCIONES SEQ

Definimos una fecuencia con Seq(), una secuencia es una estructura de datos que almacena elementos por
posición, tienen que ser del mismo tipo, las secuencias permiten almacenar valores repetidos, a diferencia de los
conjuntos, los sets, y mantienen el orden de inserción.

Si a esta secuencia le concatenamos otra, cada operación sobre una colección genera una nueva colección. Nunca
va a modificar la colección original
Coloca los resultados de la secuencia en orden

Si imprimimos la secuencia original veremos que no se han modificado los valores. Podemos almacenar estos
resultados en una variable

Podemos concatenar nuevos elementos sobre la secuencia, generando una nueva colección.

Si volvemos a imprimir la secuencia original, no estará modifcada. Cada operación que generemos sobre una
colección genera una nueva colección, jamás almacena el original.

Para recorrer una secuencia usamos un bucle for

Pero también tenemos las funciones de orden superior disponibles para las colecciones, así que podríamos
recorrerla también con foreach.

También tenemos funciones que permiten transforamr y generar una nueva colección como resultado, disponibles
en todas las colecciones de scala, por ejemplo
COLECCIONES CLASS CASE CLASS OBJECT

CLASES

Estructura de datos que tiene un estado, el estado lo determina los valores de sus parámetros, y que tendrá un
comportamiento, que va a estar definido en las funciones que tenga esta clase.

Para definir una clase usamos la palabra reservada class.

class NombreClase(nombreParametro: tipoParametro)

Clase alumno con dos parámetros que son parte del constructor, el constructor es la función que se llama para
crear una clase. La función del constructor viene dada por los parámetros que espera la clase.

Para crear una instancia de una clase usamos la palabra reservada new seguida de la clase.

Al constructor le podemos pasar los parámetros por nombre o sin necesidad de nombrarlos, si no los nombramos,
es importante el orden de los parámetros, se mapearán a la posición que ocupan. Si indicamos el nombre del
parámetro el orden es irrelevante.

Para acceder a los parámetros de la clase no nos deja y nos da un error diciendo que ''n'' no es miembro de la clase.
Esto sucede porque los parámetros de una clase siempre van a ser privados e inmutables.

Esto nos lo podemos saltar usando en la definición de los parámetros/atributos la palabra reservada var. Por
defecto son imutables, pero como var se usa para definir variables mutables, al especificarlo, pasan a ser mutables.
Ahora sí podemos acceder a los atributos de la clase, porque al definir el tipo var, automáticamente los atributos
pasan a ser mutables y públicos

Ahora a la clase alumno le añadimos una función que va a imprimir por consola el nombre y el apellido

Los objetos que creamos de una clase que tiene parámetros/atributos inmutables tienen disponible las funciones
que contienen,a través de esas funciones sí podemos acceder a los valores.

Por tanto las clases tienen un estado que viene definido por los valores de los atributos y un comportamiento
definido por los métodos que contiene.

CASE CLASS

Clase que no tiene un comportamiento pero sí un estado fijo. En una case class todos los atributos son inmutables
pero públicos por defecto.

Para definir una case class usamos las palabras reservadas case class

Si necesitamos definir un comportamiento, tenemos que definir una clase, no una case class. Una case class por lo
general mantiene únicamente un estado, no tiene un comportamiento

Para instanciar una case class no hace falta instanciar la palabra reservada New, basta con usar el nombre de la
clase y la llamada al constructor con los parámetros
Hemos creado un objeto de la case class, que además vemos que es más legible. Podemos acceder a cada uno de
sus atributos a pesar de no haber sido definidos con la palabra reservada var, porque son públicos, podemos
acceder a cada uno de sus valores.

SINGLETON OBJECT

Objeto de utilidades. Estará definido a nivel de todo el programa, va a ser una instancia para todo el programa, y no
se va a poder cambiar, no se va a poder crear un nuevo objeto de este tipo, no se va a poder volver a instanciar.
Definimos un objeto singleton recurriendo al keyword object
Y definimos el comportamiento que va a tener este objeto.

Estos objetos son utilidades, funciones, para realizar en el resto del código.

Para hacer uso de las funciones que tenemos en el objeto singleton, basta con hacer referencia al nombre del
objeto seguido de la llamada a la función

Nombreobjeto.funcion()

Es un objeto de funciones de utilidades, se llaman directamente haciendo referencia al objeto, no hay ningún new
por ningún lado ni ninguna variable que apunte a este objeto, sino que directamente hacemos una llamada, una
referencia, al identificador del objeto definido y hacemos llamadas a las funciones que contiene.

COMPANION OBJECT

Objeto singleton que está asociado a una clase, ya sea regular o case class. Se define de la msima forma que un
objeto singleton, con el requisito de estar en el mismo fichero fuente donde esté la clase a la que va a acompañar y
tiene que tener el mismo nombre que la clase.

Por ejemplo, tenemos la case class Alumno, para definir su companion object u objeto de compañía:
Usamos la keyword object

Las case classes no incorporan comportamiento pero un objeto singleton que la acompaña y que va a ser un
companion object, un común para todas las instancias de la clase alumno, si que puede implementar estos
comportamientos que no implementa la case class.

Así definimos el método imprime que recibe un alumno y devuelve un unit porque lo que va a hacer es imprimir
por consola el nombre y el apellido. Y ya tenemos acceso directo a los elementos de este objeto alumno que está
tomand como parámetro la función imprime, estamos accediendo a sus valores.

Para llamar a la función del companion object, hacemos directamente la referencia al objeto y llamamos a la
funcion()

EJERCICIOS SCALA

Vamos a implementar un caso práctico, una app de Scala que va a planificar viajes en tren: JourneyPlanner.
Veremos POO, programación funcional, trabajar con parámetros y clases...

Para esta app usaremos clases Train, Stations, Times, JourneyPlanner y Scheludes.

EJERCICIO: Definir una clase.


La claase se llama Train, debe estar en la carpeta src/main/scala (la jerarquía por defecto de carpetas que provee el
ide al crear un nuevo proyecto de Scala). Una vez definida la clase, implementada, debemos instanciar objetos
desde un worksheet.
Sobre la carpeta scala > New > Scala Class > Class

Para testearlo desde un worksheet, tenemos que crear uno.

Sobre la carpeta scala > New > Scala Worksheet

Los worksheet son una interfaz visual que funcionan como si fuese un intérprete, muy parecido al de Python pero
sobre Scala.

Para instanciar un objeto hacemos uso de la palabra new.

new Train()

Ya tenemos el primer objeto de nuestra clase Train. Si lo queremos añadir a una variable usamos la palabra
reservada val o var

val para variables inmutables (que cuando se define su valor no puede actualizarse)

var para variables mutables (sí se puede actualizar, pero siempre para el mismo tipo al cual se ha definido en un
principio)

La diferencia de tipos es el mecanismo mediante el cual el compilador sabe cuál es el tipo de datos que va a
almacenar una variable sin que se le especifique. De forma implícita es capaz de inferir el tipo de datos que va a
almacenar cada variable.

EJERCICIO: DEFINIR PARÁMETROS DE CLASE

A la clase Train hay que añadir un parámetro de tipo entero.

Si vamos al worksheet vemos que este ya nos marca error porque hemos cambiado la definición de la clase, y le
estamos pidiendo que ahora espere un parámetro, no podemos llamar a Train si no le pasamos el parámetro. Si en
lugar de un int le pasamos un string, dará error también, no es el tipo de parámetro que espera.

Lo hemos cambiado pero en el worksheet nos está dando un error ahora, porque el cosntructor no espera un
parámetro. Ello ocurre porque hemos cambiado el código fuente pero no hemos compilado el proyecto, para
compilarlo hacemos click en Build project.

EJERCICIO: PROMOCIÓN DE PARÁMETROS DE CLASE

Promover parámetros de clase es promover los parámetros de una clase a atributos.

Desde un worksheet tenemos que instanciar un objeto de la clase Train e intentar acceder a su parámetro de clase
''number''. Añadir un paráemtro de clase a la clase Train, pero que seal primer parámetro, de nombre 'kind' y de
tipo 'String. Debemos convertir ambos atributos inmutables y una vez convertidos, e implementado, desde un
worksheet, crear un nuevo Train e intentar acceder a ss atributos 'number' y 'kind'

Para acceder al atributo number, desde el worksheet:

El compilador da un error, el valor number no es un miembro de Train, no lo reconoce como un atributo accesible,
debido a que number es únicamente usado como parámetro del constructor, será accesible en el cuerpo de Train
pero no desde fuera. Cuando estamos implementando la clase podremos hacer uso de él, pero cuando estamos
instanciando un objeto number no será accesible desde fuera.

Definimos kind como otro parámetro de clase, el primer parámetro, y promocionamos ambos parámetros de clase
como atributos inmutables, para poder hacer esto lo que tenemos que hacer es añadir var o val, accesibles desde
fuera de la clase, desde un objeto:

Construimos el projecto en build project. Con esta cualificación de los parámetros de clase automáticamente el
compilador sabe que van a ser atributos y que van a ser accesibles desde fuera de la clase, desde un objeto.
Añadimos el nuevo parámetro a los distintos objetos que habíamos creado antes

Ya podemos acceder a los parámetros porque han sido promocionados a atributos de la clase.

print Muestra por pantalla


println Muestra por pantalla y añade un salto de línea

EJERCICIO: PROMOCIÓN DE PARÁMETROS DE CLASE

Definir una nueva clase 'Time' con dos parámetros de clase de tipo entero (int): 'hours', 'minutes'. Los convertimos
como atributos de la clase (directamente cuando lo definamos ya podemos definirlo como atributos de la clase).
Dentro del cuerpo de constructor de Time, añadimos comentarios de TODO (anotaciones para que más adelante
recordemos implementar lo que necesitamos):
TODO: veritifcar 'hours' entre 0 < x < 23
TODO: verificar 'minutes' entre 0 < x < 59
Sobre Scala > New > Scala Class > Class
'Time'

Los promovemos a atributos de clase y añadimos los dos comentarios TODO

EJERCICIO: DEFINIR UN ATRIBUTO

Dentro de la clase 'Time' debemos definir un atributo inmutable 'asMinutes' (no tiene que ser un parámetro de
clase, sino un atributo de la clase) que debe devolver la representación de la clase en minutos, multiplicando su
atributo 'hours'*60 y sumándole 'minutes'
'hours'*60 + 'minutes'

Es decir, este atributo hará uso de los parámetros para obtener su valor.

Se declara dentro del cuerpo de la clase.

EJERCICIO: DEFINIR UN MÉTODO


Definir un método para la clase 'Time' llamado 'minus', cuyo parámetro de entrada debe ser de tipo 'Time', el tipo
de retorno será 'Int' y debe devolver la diferencia entre ambas instancias de 'Time' en minutos. Ambas instancias
de time tienen la representación del tiempo en minutos, se puede devolver la diferencia de ambas.

En la clase 'Time' definimos un método a partir de la palabra reservada def

def nombreMetodo(parametro : tipoParametro): tipoRetorno = ???

Los ??? nos permiten definir que no sabemos cuál será la implementación de esta función, sirve para escapar
posibles errores en la definición. Es una forma de hacer explícito que no sabemos cómo vamos a implementar esto.

def es una palabra reservada para definir funciones y métodos

A la derecha del igual debe ir la expresión que va a devolver el método, la expresión que calcula la diferencia entre
uno y otro sería

this.asMinutes - that.asMinutes

Con esto ya tendríamos el cálculo de la diferencia entre ambas horas.

Estamos usando this porque es el equivalente del self en python. En este caso podríamos omitirlo, ya que será
llamado por un objeto y va a buscar esta variable en su atributo, no hace falta ir a buscarlo, pero el that si es
necesario ya que es un objeto que está recibiendo como parámetro de entrada, y hay que acceder a su atirbuto
asMinutes

Lo invocamos desde el worksheet:

EJERCICIO: DEFINIR UN OPERADOR

Definir un operador en la clase 'Time', añadiendo el método '-', funcionará como un alias de la función 'minus', en
el cuerpo de '-' tenemos que hacer uso de la función 'minus', tenemos que invocarla.
Esta función hará una llamada a la función minus pasándole el argumento, y devolverá el resultado que devuelva
minus. La expresión a evaluar es la expresión de invocación de la función minus

minus(that)

En Scala tenemos las notaciones sinfija, postfija e infija, dependiendo del nº de parámetros que tiene la función
podemos invocarlo, dependiendo del nombre de la función si es simbólica o no tendremos que usar una u otra, en
algún caso la postfija está completamente desaconsejada, en este caso estamos haciendo uso de la notación infija:

El resultado de cualquiera de las tres formas de invocarlo será el mismo.

EJERCICIO: USO PARÁMETROS DEFECTO

Adaptar el código para que los parámetros de la clase 'Time' (hours y minutes) tengan el valor 0 por defecto.

Para definir un valor por defecto le asignamos el valor junto a la definición:

Esto al final es la representación de un constructor, de una función, que construye una instancia. Al constructor le
estamos pidiendo que tenga dos parámetros cuyo valor por defecto será 0.
Ahora si instanciamos un nuevo objeto de Time, podemos pasarle parámetros o no, si no lo hacemos, tendrán los
valores por defecto. También podemos construir un nuevo objeto pasándole sólo un atributo, y que el otro recoja
el valor por defecto.

Recordemos que los parámetros se pueden pasar desordenados siempre que indiquemos su nombre.

EJERCICIO: USO DE PACKAGES

Debemos definir un paquete donde vamos a alojar nuestro programa. Sirven para tener organizado el código. La
estructura de directorios determina la jerarquía de paquetes.

Se debe crear un paquete llamado 'com.ntic.clases.planner' dentro de 'src/main/scala'

Reubicamos las clases 'Time' y 'Train' en este paquete:


-Se puede hacer usando el asistente del IDE: "refactor > Move.."
-O moviendo los ficheros dentro del paquete y posteriormente añadiendo el indicador de paquetes. Se usa la
palabra reservada package para que el compilador sepa dónde debe buscar las fuentes.

Instanciaremos la clase Time desde un worksheet.

En la carpeta scala > New > Package

Haciendo click sobre la clase > Refactor > Move Class


Otra opción es seleccionar ambos ficheros y arrastrarlos hasta el paquete.
El IDE lo hace automáticamente pero es importante verificar que en la primera línea de ambas clases venga la
palabra package con la referencia al paquete del que forman parte.

En el worksheet deberemos tener un import con la referencia del paquete. Si no, no sabría encontrar las clases.

EJERCICIO: DEFINE CASE CLASES

Convertir en case class las clases 'Time' y 'Train', eliminar ' val' de los parámetros de clase, incluso si no molesta.
Eliminar 'new' de Time.fromMinutes, incluso si no molesta. La clase Time tiene un objeto de compañía o
companion object, y este companion object define uana función 'fromMinute', que es un método factoria de
construcción de objetos de la clase Time, la clase que acompaña a este objeto.
Pruébalo desde un worksheet.

Para definir una case class recurrimos a la palabra reservada val.

Ambos val son redundantes, las case clases a diferencia de las clases, automaticamente son convertidos en
atributos, no es necesario usar la palabra reservada val para promoverlos a atributos, con ello ya tendríamos la
definición de una case class.

Diferencia entre clase regular y case class, las case class son clases con algunas funcionalidades extra, talesque:

-En las cas class los parámetros de clase son automáticamente promovidos a atributos de clase

- Automáticamente definen una función que vamos a usar para construir, aunque no esté definida, la autogenera el
compilador de scala, que es la función apply. Es por eso que podemos hacer esta manera de instanciar a nuevos
objetos de esta clase sin necesidad de usar la palabra reservada new.

Si nos fijamos ahora, al instanciar la clase Train, new es redundante, dado que ahora es una case class. Podemos
borrarlas.

-Al instanciar con clases regulares, nos generaba una respuesta que no era legible, una ristra de carácteres
alfanuméricos, pero en una case class devuelve el contenido de forma más legible, porque automáticamente
sobreescriben la función toString para que sean más legibles los objetos cuando los imprimimos por consola.

EJERCICIO FILTER:

Añadir el método trainsAt a JourneyPlanner, que tome como parámetro 'station' de tipo 'Station', debe devolver
todos los objetos de tipo Train que contengan el valor de station en su atributo 'stations'. ¿Qué tipo tiene sentido
que tenga el valor de retorno de esta función?

Filter es una función de orden superior que generará una nueva colección dependiendo de la evaluación de la
condición que se le pase a filter. Se le pasa una expresión booleana

coleccion.filter(condicion)

Esto devuelve una colección de todos los trenes cuyo atributo station contiene a la estación que se le pasa por
parámetro. Esto es un paradigma de programación funcional, declarativo, decimos qué queremos hacer: queremos
filtrar todas las estaciones de cada uno de los trenes que contengan a la estación, pero no le decimos cómo lo
queremos hacer, eso ya por debajo filter tiene mecanismos para evaluar esta expresión que se le pasa

Otras formas de implementarlo

EJERCICIO: USA PATTERNS

Usar los patrones tupla para acceder a cada uno de los campos de la tupla en el método 'stopsAt' de la clase
JourneyPlanner,

Hasta ahora estamos usando una tupla pero sin darle nombre a los elementos de la tupla

Pero podemos filtrar por un patrón, desechar este filtro y buscar directamente por el patrón

schelude es una colección de tuplas de time y station


Seq[(time, Station)]

Queremos buscar por patrón, uqeremos decir que este station debe busca

Con los `´ le estamos diciendo a Scala que station hace referencia a la station que está definida anteriormente

EJERCICIO: USAR OPTION

Añadir el método 'timeAt' a 'Train'

Añade un parámetro de tipo Station


Devuelve un 'Option' de 'Time':

'Some' de 'Time' si el 'Train' se detiene en la estación

Si no, devuelve 'None'


FALTAN 2H DE EJERCICIOS Y

13MIN DE HERENCIA Y POLIMORFISMO

23 MIN DE COLECCIONES Y WEAS

También podría gustarte