20250121Interfaces Teoria - Contenido educativo
Ajuste de pantallaEl ajuste de pantalla se aprecia al ver el vídeo en pantalla completa. Elige la presentación que más te guste:
Voy a grabar esta clase, por lo tanto si habláis me dais consentimiento para poder grabarlo, ¿vale?
00:00:00
Entonces estamos viendo clases abstractas, polimorfismo, interfaces y lo que sea, ¿vale?
00:00:06
Entonces las clases abstractas hemos entendido que son, hemos empezado a trabajar con ellos,
00:00:11
hemos visto el concepto de que puedo tener el mismo método en clases distintas
00:00:16
y que Java en automático selecciona cuál es la mejor implementación de ese método
00:00:20
en base a la instancia del objeto mismo
00:00:28
no en base a la referencia
00:00:31
hemos visto que yo puedo hacer un downcasting
00:00:32
para utilizar métodos de un hijo
00:00:35
desde una referencia que es de tipo padre
00:00:41
pero la instancia de tipo hijo
00:00:47
y para saber si esta referencia de tipo padre
00:00:49
eso no es una instancia de tipo hijo
00:00:52
siempre tengo la posibilidad de usar el
00:00:56
instance of
00:00:57
y hoy vamos a ver
00:00:58
la última parte de esto
00:01:01
que son las interfaces
00:01:03
hemos dicho que
00:01:05
en Java
00:01:07
no existe la herencia
00:01:08
múltiple, eso quiere decir que yo
00:01:11
cuando heredo de otra clase
00:01:13
tengo que decidir
00:01:15
una sola clase y desde
00:01:17
esa heredo, me importo todos los
00:01:19
digamos que heredo todos los
00:01:21
métodos, las variables, etc.
00:01:23
Pero no puedo, en ningún caso, heredar desde dos clases a la vez. Puedo hacer una cadena, esto hereda de esto, que hereda de esto, que hereda de esto, pero no puedo una misma clase decir hereda de la clase A y hereda también de la clase B.
00:01:25
pero hay veces en el que esto podría ser útil
00:01:40
hay veces en el que yo digo
00:01:45
sí, esta clase debería hacer cosas que hace la clase A
00:01:47
y también debería poder ser capaz de hacer cosas
00:01:50
que hace una clase B
00:01:54
entonces para intentar solucionar esto
00:01:56
en otros lenguajes de programación como C++
00:02:00
se puede hacer herencia múltiple
00:02:03
pero Java como no lo permite
00:02:05
Pues introduce otro mecanismo parecido, pero un poquito distinto, que son las interfaces, ¿vale? Es un concepto parecido a las clases abstractas, ¿vale? Es decir, defino una estructura formal de métodos, una serie de métodos, un conjunto de métodos, que mi clase seguramente va a tener.
00:02:07
Voy a crear un contrato en el que digo, oye, mira, yo soy la interfaz algo
00:02:31
Cualquier clase que diga que va a utilizar, ahora veremos cómo se dice técnicamente
00:02:42
La interfaz algo, tendrá necesariamente que implementar este método, este método, este método
00:02:50
De esa forma, si yo sé una clase cualquiera, esté donde esté
00:02:57
Si usa, si hace algo, se implementa, se dice, la interfaz a algo, seguramente sobre esta clase puedo llamar estos tres métodos.
00:03:03
¿Por qué? Porque es un contrato. La interfaz me dice, si quieres implementar esta interfaz, necesitas haber implementado estos tres métodos.
00:03:14
Es lo mismo que la clase abstracta en un cierto sentido, solo que la clase abstracta podía también tener una parte concreta y luego tener algunos métodos abstractos. En vez, en una interfaz es como si fuera una clase abstracta donde todos los métodos son abstractos.
00:03:24
¿Sí? Esto me permite que en una clase yo pueda extender, entonces heredar de una clase, pero implementar otras, otras interfaces.
00:03:38
Yo puedo implementar cuantas interfaces me da la gana, ¿vale?
00:03:57
Entonces, si yo tengo mi clase, le digo implementas esta interfaz, esta otra y esta otra,
00:04:01
y yo sé que tendrá que tener los métodos de las tres interfaces, los métodos definidos como abstractos en las tres interfaces que yo voy a implementar.
00:04:05
Se parecen a las clases abstractas, pero a diferencia de estas, todos sus métodos son obligatoriamente abstractos.
00:04:19
Y como los métodos son obligatoriamente abstractos, no se pone abstracto.
00:04:26
se da por hecho
00:04:30
¿vale? porque es la primera vez
00:04:32
ahora lo veremos, que cuando yo defino
00:04:35
una interfaz, no la defino
00:04:37
como public class
00:04:39
la defino como public interface
00:04:40
entonces es una cosa distinta de las clases
00:04:43
las clases son clases, estas son interfaces
00:04:47
si yo estoy definiendo una interfaz
00:04:49
en automático sé que
00:04:51
todas las declaraciones de sus métodos
00:04:53
van a ser abstractas
00:04:55
y como sé que tienen que ser abstractas
00:04:56
no hace falta poner que son abstractas, así como no hace falta poner que la interfaz es abstracta, ¿vale?
00:04:58
Es una forma, digamos, de simplificar el concepto de la clase abstracta, de decir, en vez de ponerte abstracta por todo lado,
00:05:06
pues te doy esta forma de hacerlo, que es con la interfaz, si tú estás haciendo una clase que sólo tendría métodos abstractos,
00:05:13
en vez de hacerte la clase abstracta con todos los métodos abstractos, hazte una interfaz declarando los métodos,
00:05:21
Y estos serán los métodos abstractos que se tendrán que implementar.
00:05:26
Entonces está la clase concreta, está al lado opuesto la interfaz, donde todos los métodos son abstractos,
00:05:32
y luego está la clase abstracta, que es una mezcla de los dos.
00:05:39
Es una clase que puede tener una parte concreta y puede tener una parte abstracta.
00:05:43
Entonces, dependiendo de lo que necesito yo, uso una cosa u otra.
00:05:47
Si todos mis métodos son abstractos, ¿puedo hacer una clase abstracta cuyos métodos son todos abstractos?
00:05:52
Sí. ¿Por qué no es una buena idea?
00:05:59
Lo mismo en la interfaz.
00:06:02
Porque si yo hago una clase abstracta, estoy bloqueando la clase que estoy creando, la esfuerzo a heredar de mí.
00:06:09
Y entonces no puede heredar de otra.
00:06:17
Y si mi clase no le proporciona nada porque todo es abstracto, es mejor hacer una interfaz.
00:06:19
Así desbloqueo la herencia y mi clase puede heredar de otra clase si quiere o necesita y implementar mis métodos gracias a la implementación de la clase abstracta, de la interfaz.
00:06:24
Hay una pregunta, si y no, porque si tú defines que está la variable número de lados, que nosotros pusimos, entonces no es una interfaz, porque has concretizado algo.
00:06:38
y si tú le pones en
00:07:00
figura geométrica un
00:07:02
descripción que
00:07:03
implementa con
00:07:06
soy una figura de enhelados
00:07:08
¿vale? pues entonces
00:07:10
ya no es un interfaz
00:07:12
si tú lo consideras
00:07:14
como le quitas a ese ahí
00:07:16
y le pones solo calcular área, calcular perímetro
00:07:18
calcular no sé qué
00:07:20
que vale para todas las cosas, pues sí, podría ser
00:07:22
un interfaz
00:07:24
¿sí?
00:07:25
entonces
00:07:26
Entonces, tres niveles de abstracción, entre comillas
00:07:27
La clase es todo concreto
00:07:32
La clase abstrata, algo concreto y algo abstrato
00:07:34
La interfaz, todo abstrato
00:07:37
En Java se declaran utilizando la palabra interface en lugar de class
00:07:39
O sea, en vez de public class hago public interface
00:07:47
Para crear una clase que escriba código para los métodos
00:07:49
indefinidos aún, porque son abstractos
00:07:53
de una interfaz, pues lo que hago
00:07:57
es usar la palabra reservada implements
00:08:00
en vez que extends
00:08:02
entonces public class mi clase
00:08:04
implements mi interfaz
00:08:09
se pueden declarar referencias a objetos
00:08:13
cuyos tipo sea una interfaz en lugar de una clase
00:08:20
o sea, como antes yo podía hacer
00:08:23
una variable de tipo clase abstracta,
00:08:26
ahora puedo hacer una variable
00:08:29
que como tipo tenga una interfaz.
00:08:31
¿Sí?
00:08:35
Estoy hablando de la referencia, de la variable.
00:08:36
No puedo hacer un new de una interfaz.
00:08:38
¿Por qué no puedo hacer un new de una interfaz?
00:08:41
Porque todos sus métodos son abstractos
00:08:44
y mientras que no haya una concretización de esos,
00:08:45
no puedo hacerlo.
00:08:48
Pero sí puedo hacer mi interfaz x
00:08:49
es igual a new
00:08:52
mi clase, asumiendo
00:08:54
que mi clase implements
00:08:57
mi interfaz
00:08:59
¿si?
00:09:00
entonces, la interfaz
00:09:03
se vuelve un comodín
00:09:04
para decir, oye mira, cualquier
00:09:06
objeto de tipo mi interfaz
00:09:08
puede ser referenciado
00:09:10
o sea, puede hacer una referencia
00:09:12
de tipo mi interfaz a cualquier
00:09:14
objeto que implemente esta
00:09:16
interfaz, entonces sé que allí
00:09:18
dentro tendrá los métodos abstractos
00:09:20
que yo he definido en mi interfaz. Si mi interfaz definía los métodos dibuja y escribe, pues
00:09:22
cualquier objeto de tipo interfaz tendrá dibuja y escribe. Si no, no habría implementado
00:09:30
la interfaz. Esta forma de proceder tiene sentido para definir un objeto en función
00:09:36
del tipo más genérico para utilizar mecanismos como el polimorfismo. Aquí también estamos
00:09:43
utilizando polimorfismo, de ello te declaro que hay el método calcularia como interfaz
00:09:48
y luego todos los que implementan la interfaz que se llama se puede calcular área, pues tendrán que tener el método calcular área.
00:09:53
Su principal función es establecer y estabilizar las interfaces como prototipo de métodos de una clase para poder desarrollar y así coordinar varios equipos de trabajo.
00:10:04
¿Qué quiere decir esto?
00:10:15
Yo puedo, por un lado, crear una interfaz y decir, oye, mira,
00:10:17
estas clases, la clase que implementa esta interfaz tendrán que tener estos métodos.
00:10:23
Una vez que he definido esta interfaz, yo puedo dividir el trabajo entre
00:10:29
personas que implementarán la clase A que implementa esta interfaz.
00:10:34
Entonces, ¿dónde se dará el cuerpo de estos métodos?
00:10:40
Pero al mismo tiempo, yo puedo decir a otro grupo de trabajo, oye, mira, tú tendrás en un futuro una clase que implementa esta interfaz. Ahora, tú puedes ya desarrollar utilizando objetos de tipo esta interfaz y usar sus métodos como si ya estuvieran implementados.
00:10:44
Luego en un futuro se implementarán con el trabajo que ha hecho el otro equipo
00:11:05
Pero ya tú puedes seguir trabajando
00:11:11
Asumiendo que el método calcular área, por ejemplo
00:11:13
De la interfaz se pueden calcular áreas
00:11:17
Pues calculará el área, funcionará
00:11:19
Ahora tú lo puedes ya utilizar en tu código
00:11:22
Después hacemos un ejemplo para entender lo que estamos diciendo
00:11:26
Pero tú ya lo puedes utilizar
00:11:28
Luego cómo lo hará y qué funcionará lo veremos más adelante
00:11:30
Cuando ya estará lista el otra clase. Y si tú necesitas sí o sí un objeto de la otra clase por algún lado, pues te puedes crear un objeto mock, un objeto falso, un objeto ficticio que usarás en tu programa por ahora, que da un resultado siempre fijo sin saber qué hace.
00:11:35
y cuando en un futuro ya estará listo el trabajo del otro equipo, pues lo integramos y funciona.
00:11:55
Ahora luego probamos a hacer un pequeño ejemplo sobre este tema para que entendáis qué quiero decir.
00:12:01
Veamos un poco. El equipo que debe utilizar... Bueno, esta es la explicación misma.
00:12:08
El equipo que debe utilizar objetos que implementan dicha interfaz, basta con que declaren en su código una referencia a dicha interfaz,
00:12:12
aunque no esté todavía compilada ninguna clase que la implemente.
00:12:20
Yo tengo una referencia de tipo esta interfaz, pero no tengo una implementación de esta interfaz. La tendré en un futuro. Y aquí en mi código yo puedo usar tranquilamente esta interfaz haciendo lo que me haga gana con esa interfaz.
00:12:25
los equipos que creen clases que implementan
00:12:37
esta interfaz están a su vez
00:12:41
desacoplado de los equipos
00:12:43
que la utilizan, esto es para que
00:12:45
me permita trabajar
00:12:47
en paralelo entre grupos
00:12:49
de trabajo
00:12:53
en términos técnicos es desacoplado
00:12:54
yo no dependo de ti y tú no dependes
00:12:57
de mí, en un futuro
00:12:59
podremos funcionar juntos
00:13:01
porque hemos definido esta interfaz
00:13:03
este punto de contacto, los métodos
00:13:05
que se pueden utilizar, están definidos aquí
00:13:07
y yo los utilizo
00:13:09
sin saber
00:13:10
qué harán adentro y al mismo tiempo
00:13:12
por otro lado
00:13:15
tú lo estás implementando
00:13:16
sin saber quién los utilizará
00:13:19
y cuándo lo utilizará
00:13:20
los equipos
00:13:24
que creen
00:13:27
este es el concepto
00:13:28
de mock, si en algún
00:13:31
momento, pero yo necesito
00:13:33
por alguna razón, necesito
00:13:35
una implementación, necesito hacer un new
00:13:37
para hacer algo
00:13:39
pues lo que puede hacer es crearme un objeto
00:13:41
falso, un objeto mock
00:13:43
¿vale? que es una clase donde
00:13:44
los métodos, los implementos, pero que hagan
00:13:47
nada, si es un método que tiene que calcular el área
00:13:49
y yo lo implemento con return a 3
00:13:50
cada vez que calcularé el área
00:13:53
pues me devolverá 3
00:13:54
pero lo puedo utilizar, puedo crear objetos de esos
00:13:56
pero claramente serán inútiles
00:13:59
¿sí?
00:14:01
ejemplo, ¿vale?
00:14:05
para que entendamos un poquito
00:14:06
esta, por ejemplo, existe
00:14:08
la interfaz comparable
00:14:10
la interfaz comparable
00:14:12
me transforma mi
00:14:14
objeto en un objeto
00:14:16
comparable
00:14:18
¿qué quiere decir? cuando yo
00:14:19
tengo un objeto, el objeto
00:14:22
gato
00:14:24
y quiero saber
00:14:25
y quiero implementar la interfaz comparable
00:14:28
entonces gato implements
00:14:31
comparable, la comparable
00:14:32
me dice que obligatoriamente
00:14:35
tengo que implementar el método
00:14:37
int compareTo
00:14:39
objeto, está este método que yo tengo que implementar. ¿Y qué me dice? Pues si yo
00:14:40
implemento este objeto, implemento este método, tengo que hacer que si mi objeto, el gato
00:14:48
dice, es más grande que el objeto pasado por aquí, pues yo te tengo que devolver un
00:14:55
número positivo. Si es más pequeño, te tengo que devolver un número negativo. Y si son
00:15:05
iguales, pues te tengo que devolver cero. O sea que este es un método general. Yo no
00:15:12
sé cómo se comparan dos gatos. Se podrían comparar por edad, se podrían comparar por
00:15:19
tamaño, se podrían comparar por, no lo sé, por color, qué sé yo. Pero yo estoy diciendo
00:15:24
quiero poder comparar gatos
00:15:31
para poder comparar gatos
00:15:33
yo lo que voy a hacer es
00:15:35
implementar la interfaz comparable
00:15:37
y la interfaz comparable me obliga
00:15:39
a implementar este método
00:15:42
a partir de ahora
00:15:43
¿vale?
00:15:46
yo, mis objetos
00:15:47
gato en este caso
00:15:49
pues son comparables entre ellos
00:15:51
los puedo ordenar
00:15:53
¿sí?
00:15:55
entonces, esto me permite
00:15:57
por otro lado, utilizar otra clase que pilla objetos, sean cual sean, pueden ser gatos,
00:15:59
pueden ser cocodrilos, me da igual, y los ordena de mayor a menor. ¿Qué tipo tendrán
00:16:09
estos objetos? Repito la pregunta. Por un lado tengo mi clase gato, que implementa,
00:16:16
Comparable, hemos dicho
00:16:33
Entonces, eso quiere decir que la clase gato
00:16:37
Por algún lado tendrá que implementar compare to
00:16:41
Y a partir de que ha implementado este método
00:16:46
Yo puedo comparar gatos
00:16:53
Puedo decir si este gato es más grande que esto
00:16:57
Si este gato es más pequeño que esto
00:16:59
Si este gato es igual de...
00:17:00
¿En base a qué?
00:17:03
En base a lo que yo sé de los gatos. Es un problema mío de yo estoy creando el objeto gato. Entonces, yo quiero poderlos comparar. Yo sé cuando un gato es mayor que otro gato o un gato es menor que otro gato. Lo defino aquí dentro.
00:17:04
Si es por edad, pues diré, si el gato Dís tiene más años que el gato que me has pasado aquí como objeto,
00:17:21
pues entonces devuelve, no lo sé, 30, que es un número positivo.
00:17:31
Si tiene la misma edad, devuelve 0.
00:17:37
Si el Dís tiene una edad menor que el gato que me has pasado aquí como parámetro, devuelve menos 30.
00:17:40
he hecho las especificaciones que me pide aquí
00:17:47
ahora, por otro lado
00:17:53
completamente sin saber que el gato
00:17:55
implementa el comparable, yo puedo hacer una clase
00:17:59
que lo que hace es ordenar objetos
00:18:02
entonces, si aquí tendré objetos
00:18:04
y lo que quiero decir es
00:18:08
ponme primero el menor, que por ejemplo es este aquí
00:18:11
luego el siguiente menor, luego el siguiente menor
00:18:13
¿Vale? Para poder hacer esto yo tengo que comparar los objetos entre ellos. Y cuidado, no sé cómo se comparan los objetos. Porque no sé si estos objetos serán gatos, serán cocodrilos, serán personas. ¿Vale? No lo sé.
00:18:15
yo quiero hacer una cosa tan genérica
00:18:36
que me dice, tú dame objetos
00:18:38
y yo te los ordeno
00:18:40
ahora, estos objetos
00:18:41
para que esto funcione
00:18:44
¿qué tipo tendrán que tener?
00:18:46
tú me dices, tipo gato
00:18:50
entonces me funcionaría solo como gato
00:18:51
con gatos
00:18:53
no me funcionaría con persona
00:18:54
¿qué tipo le doy a estos señores?
00:18:56
¿le doy object?
00:18:59
no
00:19:01
porque si yo hago perro
00:19:02
que no implementa comparable
00:19:04
no puedo comparar dos perros
00:19:06
entre ellos, entonces object
00:19:08
es demasiado genérico, ¿qué tipo le doy?
00:19:10
ya, pero el método
00:19:22
estará aquí
00:19:23
esto es lo que me permite
00:19:24
compararlo
00:19:27
solo que si yo aquí le digo gatos
00:19:28
o sea que estos son gatos, son
00:19:31
objetos de tipo gato, pues entonces
00:19:33
solo me funcionaría entre gatos
00:19:35
no quiero, quiero que sea más genérico
00:19:37
entonces le digo, le pongo object, así le puedo poner
00:19:39
lo que me da la gana, pero el problema
00:19:41
que vosotros, todos los objetos que habéis hecho hasta ahora, no tienen el método para compararlo.
00:19:43
Las personas, vosotros no las podéis comparar.
00:19:50
Los instrumentos musicales, vosotros no los podéis comparar.
00:19:54
No podéis decir si un instrumento musical es mayor o menor que otro.
00:19:57
Entonces, ¿cómo puedo estar seguro que estos objetos sean comparables?
00:20:03
Es decir, que el tipo que uso para este objeto será tipo comparable. Esto. Estoy usando como tipo la interfaz. Esto me garantiza que, sea lo que sea, implementará comparable. Y si implementa comparable, tengo un método para compararlo.
00:20:10
entonces son gatos, pues perfecto
00:20:37
entonces podría hacer compare tú con este
00:20:39
compare tú con este, compare tú con este
00:20:41
y ordenarlos
00:20:43
son barcos
00:20:44
pero los barcos implementan
00:20:47
compareable, por lo tanto lo puedo
00:20:49
usar aquí, pues quiere decir que tendré un método
00:20:51
para comprobar cuál de estos
00:20:53
barcos es mejor, cuál de estos barcos es mejor
00:20:55
cuál de estos barcos es mejor y ordenarlo
00:20:57
se entiende la potencia de esto
00:20:59
cualquier método
00:21:02
que tú tengas con parable lo podrás usar con este método de ordenación que he creado que es genérico
00:21:06
que no tendré que reescribir una vez para ordenar gato una vez para ordenar barco una vez para
00:21:13
ordenar string una vez para ordenar todos los objetos que tengan comparable son ordenables
00:21:19
entiende esta es la potencia de la interfaz yo me hago una interfaz luego hago programas que
00:21:25
se basan sobre la interfaz
00:21:34
y cualquier clase que implemente
00:21:36
esta interfaz puede usar
00:21:38
estos métodos
00:21:40
¿sí? ahora hacemos ejemplos
00:21:46
con comparable
00:21:48
¿sí?
00:21:48
nota, comparable es una clase que existe
00:21:51
que es importante
00:21:54
¿vale? y que cuando vosotros
00:21:56
implementáis comparable
00:21:58
hay una parte que te dice
00:22:00
que si son iguales
00:22:02
tiene que dar cero
00:22:03
¿sí? esta cosa de aquí
00:22:05
tiene que ser consistente con la implementación
00:22:08
del equals. ¿Os acordáis del método de Equals?
00:22:12
¿Vale? El método de Equals te da true si dos objetos son
00:22:16
cero. Y te da false, perdón, si dos objetos son iguales.
00:22:20
Y te da false si dos objetos no son iguales. ¿Vale? Entonces, si dos
00:22:24
objetos te dan equals true, te deberían
00:22:28
dar compare to cero. Y si te dan
00:22:32
un compare to que no es 0
00:22:37
no te deberían dar
00:22:39
equals true. Si tú has
00:22:41
hecho una implementación de equals en una implementación
00:22:44
de compare to que hacen estas cosas
00:22:46
que acabo de decir, pues los has implementado
00:22:48
mal. Porque estás
00:22:51
diciendo que dos objetos son iguales pero
00:22:52
este es mayor que esto. Entonces no son iguales.
00:22:54
No.
00:23:16
Si el método ya está implementado
00:23:17
pues ya está implementado.
00:23:19
O dicho de otra forma, si yo tengo
00:23:21
si yo tengo la clase
00:23:23
gato que implementa
00:23:25
ya comparable y luego
00:23:27
la extendo con la clase minino
00:23:29
la clase minino implementa
00:23:31
comparable
00:23:34
si yo le pongo implements comparable me dirá
00:23:34
ok
00:23:37
pero normalmente
00:23:39
se
00:23:41
se tende a sobre escribirlo
00:23:43
con los datos propios
00:23:45
claro, clase padre
00:23:46
es instrumentos musicales
00:23:58
generales, entonces no los puedes
00:24:00
comparar entre ellos porque no sabes como se
00:24:02
comparen, pero luego
00:24:04
entre pianos sí sabes cómo
00:24:06
se comparan, entre guitarras sabes cómo se comparan
00:24:08
por lo tanto, guitarra extends
00:24:10
instrumentos
00:24:12
musicales, implements
00:24:14
comparable
00:24:16
de hecho
00:24:18
es más probable, cuando la clase
00:24:20
se abstracta de esta forma
00:24:22
es más probable que la clase
00:24:24
abstracta no pueda implementar comparable
00:24:26
porque no sabes cómo comparar
00:24:28
por ejemplo, en figura
00:24:29
tú puedes decir, mi comparación es
00:24:32
Dependiendo de los números de lados
00:24:33
Entonces ya la clase abstracta podría implementar
00:24:35
Reconpervo
00:24:38
Vale, entonces ejemplo de aquí
00:24:38
Yo tengo una interfaz animal
00:24:43
¿Vale?
00:24:46
La interfaz animal no puedo construir objetos de tipo animal
00:24:47
Pero sé que cuando eres un animal
00:24:50
Lo que puedes hacer es hablar
00:24:52
Porque me estáis definiendo aquí
00:24:54
Una public interface animal
00:24:56
Con void habla
00:24:58
¿Sí? Fijaos que aquí no hay abstract por ningún lado
00:24:59
Pero este es todo abstract
00:25:02
Porque cuando es interfaz, este de aquí es considerado abstracto
00:25:04
Y de hecho, está punto y coma
00:25:07
¿Sí? Vale
00:25:09
Entonces, luego tengo la public class perro que implementa animal
00:25:12
¿Vale?
00:25:16
Y entonces estoy forzado a sobreescribir habla
00:25:17
Entonces hace guau
00:25:20
Por otro lado está la clase gato que implementa animal
00:25:21
Y habla hace miau
00:25:24
¿Están de acuerdo con esto?
00:25:26
Vale, entonces
00:25:29
¿Cómo?
00:25:30
Dímelo tú, ¿por qué pone implements en vez de extends?
00:25:32
Porque se extenden clases
00:25:42
Se implementan interfaces
00:25:43
¿Sí?
00:25:45
Entonces, implements es el
00:25:47
Lo dice aquí
00:25:50
Aquí lo hemos dicho antes
00:25:51
No, me he pasado
00:25:53
Por algún lado aquí lo dice
00:25:55
¿Aquí? Sí, implements
00:25:56
Entonces, esto me está diciendo
00:26:00
Oye, cuidado, perro podría extender otra clase
00:26:04
No está ahora bloqueado
00:26:06
si está implementando animal por lo tanto puede extender otra cosa puede extender es
00:26:07
ser vivos si quiere vale y puede implementar todas las heredar una sola implementar cuántas
00:26:13
interfaces te da la gana 678 lo pondrías aquí implements animal coma no sé qué coma no sé
00:26:21
cuánto entonces el main dentro del main yo puedo crear una referencia de tipo animal fijaos animal
00:26:27
es una interfaz, ¿vale? Es como si estuviera
00:26:34
creando una interfaz, una
00:26:36
referencia a una clase abstracta
00:26:38
donde todos los métodos son abstractos
00:26:40
¿sí? Pero cuando voy
00:26:42
a hacer la new, no puedo hacer un new
00:26:44
animal, porque la interfaz no se
00:26:46
puede, porque no tendría
00:26:48
las cosas implementadas, entonces dentro de
00:26:50
animal pongo perro y dentro de animal pongo gato
00:26:52
¿vale? Y ahora puedo hacer
00:26:54
dog.habla y cat.habla
00:26:56
¿existe habla dentro de animal?
00:26:58
Sí, pero
00:27:00
por polimorfismo, cuando
00:27:02
hago dog.habla, estará
00:27:04
haciendo esto, y cuando
00:27:06
hago cat.habla, como es un
00:27:08
gato, hará esto.
00:27:10
¿Sí? La misma cosa que
00:27:14
hemos aprendido con las
00:27:16
clases abstractas.
00:27:19
¿Dudas?
00:27:21
Puedo crear una
00:27:22
array de animales
00:27:24
y luego
00:27:25
poner dentro
00:27:27
estos objetos de aquí, y luego
00:27:29
hacer un método que hablen todos, que lo que
00:27:32
hacen es recorrerme este
00:27:34
Array de animales y decirle
00:27:36
Habla
00:27:38
Fijaos que aquí estoy usando solo animales
00:27:38
Pero sé que
00:27:42
Cualquier
00:27:44
Clase que implemente animal
00:27:45
Puede ir aquí
00:27:48
Y si ahora me creo una clase
00:27:49
Pájaro
00:27:52
Que implementa animal
00:27:59
Y que cuando habla
00:28:01
Dice pío
00:28:03
Las puedo
00:28:04
Poner dentro de este array
00:28:07
Y hacerlo trabajar
00:28:09
Porque es un animal. Esto no cambiaría.
00:28:10
Aquí he creado un método que trabaja sobre animales.
00:28:15
Entonces, me da igual qué animales luego hay adentro.
00:28:19
Yo sé que si eres un animal, si eres de tipo animal porque hay la interfaz animal,
00:28:23
los objetos que andrán aquí dentro tendrán que implementar la clase animal.
00:28:29
Y si implementan la clase animal, tienen que tener el método habla. Y por lo tanto, que sea un gato, un perro, un pájaro o un cocodrilo, pues tendrá su función habla, y yo lo puedo llamar.
00:28:36
Entonces he creado un método muy abstracto que funciona para cualquier animal. A partir de ahora tú estás en tu sistema, puedes añadir los animales que te da la gana, y sin tocar esta clase aquí, yo los hago hablar.
00:28:53
¿Entiendes? ¿Dudas? Vale.
00:29:10
Ahora, hasta aquí todo claro.
00:29:18
Ahora, existe una forma, en mi experiencia relativamente poco utilizada,
00:29:20
para que una interfaz que tiene todos los métodos abstractos,
00:29:28
tenga algunos métodos implementados.
00:29:33
O sea, una clase normal implementa todos los métodos.
00:29:38
La clase abstracta es un pasito hacia el abstracto diciendo, implemento casi todo, pero dejo algunos métodos para implementar, ¿vale?
00:29:44
La interfaz es el opuesto, todos los métodos son abstractos, pero te da, para tener flexibilidad, la posibilidad de decir, sí, pero un método, ¿vale?
00:29:54
este método de aquí, que es abstracto, que no debería estar, pero te voy a dar una implementación por defecto.
00:30:07
O sea, te voy a dar un consejo, una generalidad, que si luego tú implementas esta interfaz y no quieres implementar esto,
00:30:16
pues es como se hace por defecto, ¿vale? Por ejemplo aquí, por defecto tengo un método corre, ¿vale? Dentro de la interfaz, que lo que hace es decir que el animal corre, no define nada de cómo corre, si corre veloz, corre lento, corre a cuatro patas, corre a dos patas, no lo sé, porque no sé qué animal es,
00:30:27
Pero en general un animal corre, ¿vale? Tendrá que tener corre. Y si tú cuando implementas la interfaz animal no me defines como corre, pues tendrás esta implementación por defecto, la implementación por default.
00:30:49
Y esto, en un cierto sentido, se solapa con las clases abstractas. Pero no os olvidéis, la clase abstracta es una clase y la interfaz es una interfaz. Y la clase abstracta hereda solo uno, o sea, se puede heredar solo uno, mientras la interfaz puede heredar desde donde le dé la gana.
00:31:05
Entonces, sostancialmente aquí hacen un poco lo mismo, pero por un lado lo estoy haciendo con interfaces y por otro lado con clases. Y por lo tanto, es como una forma de decir, oye, mira, se puede hacer, si lo necesitas una vez, lo puedes hacer, si no lo quieres utilizar, no lo utilices.
00:31:26
¿sí?
00:31:46
como solo usando clase
00:31:48
puede hacer métodos concretos
00:31:50
y abstractos, utilizando
00:31:52
interfaces puede hacer métodos abstractos
00:31:53
que es lo más común y lo más obvio
00:31:55
pero en algunos casos concretos
00:31:57
si me ocurre, pues puedo hacer
00:32:00
un método por defecto, una implementación
00:32:01
por defecto, esto es como decir
00:32:04
corre, lo tienes que implementar
00:32:05
pero si decides que no, esta será la implementación
00:32:07
que usas, yes
00:32:10
tiene que tenerlo todo abstracto
00:32:15
Pero es exactamente el concepto.
00:32:21
No, con todo el método que quieras.
00:32:25
Pero estamos en interfaces.
00:32:28
Es para no pillarse los dedos.
00:32:30
Imagínate que tú tienes una clase que ya hereda de otra
00:32:32
y ahora tiene que heredar de otra clase abstracta.
00:32:35
¿Lo puedes hacer?
00:32:38
No.
00:32:40
Entonces tendrías un problema.
00:32:41
Pero yo quiero heredar de algo que tenga algunas cosas abstractas
00:32:43
y algunas cosas concretas.
00:32:47
Y no puedo heredar de otra clase.
00:32:49
Pues tengo esta interfaz con los métodos por defecto
00:32:51
Ya está, he encontrado una solución
00:32:53
Tengo que poner, ah, sí
00:32:55
Esto estoy definiendo un método
00:32:58
Por defecto
00:33:01
Una implementación por defecto de corre
00:33:02
Entonces todos los animales
00:33:04
Tendrán corre
00:33:06
Con su implementación por defecto
00:33:07
A menos que tú en emperro
00:33:10
O en gato, por ejemplo
00:33:12
Sobrescribas
00:33:15
Corre
00:33:16
Entonces en este caso se utilizaría la tuya
00:33:17
Porque la soy escrita por polimorfismo, usaría esta.
00:33:21
Pero perro que implementa animal, entonces necesita que haya habla y corre.
00:33:25
Háblalo tiene que implementar sí o sí, porque es abstracto y si no daría error.
00:33:30
Corre decidido no implementarlo y por lo tanto uso la implementación por defecto.
00:33:35
Es muy parecido a lo que es la clase abstracta.
00:33:40
Pero no estamos hablando de clases, aquí estamos en el mundo de las interfaces.
00:33:42
Principalmente.
00:34:00
es un contrato
00:34:00
es
00:34:03
oye mira
00:34:05
haz lo que te da la gana
00:34:06
pero yo te digo que tu objeto
00:34:08
tiene que hacer estas cosas
00:34:11
y te puedo decir
00:34:13
tiene que hablar, correr, comer
00:34:14
y saltar
00:34:17
pues tú cuando implementes mi interfaz
00:34:18
esto lo tiene que hacer, es un contrato
00:34:20
si no, no funciona
00:34:22
pero te puedo decir
00:34:23
oye mira, tiene que hablar, correr
00:34:25
y saltar
00:34:27
pero correr te voy a dar yo una implementación por defecto que si tú no quieres implementarla
00:34:29
es así pero si tiene sentido que en tu propio animal pues haga una cosa un poquito distinta
00:34:39
pues entonces modifica me la tú lo puedes hacer pero si no lo haces ya lo tienes como un contrato
00:34:46
pero opcional vale las que son así sin por defecto son vinculantes obligatorias esa la
00:34:54
tiene que hacer la que te dado ya yo una vía de salida es opcional la puedes sobreescribir 1
00:35:04
de acuerdo mal y por eso ahora la pregunta obvia es si vale muy bien muy bonita la casa
00:35:13
abstracta, muy bonita las interfaces, pero ¿qué diferencia hay cuando uso
00:35:22
una clase abstracta cuando uso una interfaz? Entonces aquí
00:35:26
tenemos una comparativa de cosas entre
00:35:30
clase abstracta e interfaz, que a lo mejor no son tan
00:35:34
obvias al principio porque parecen mucho la misma cosa, pero
00:35:38
la primera en absoluto es esta cosa de que yo puedo heredar solo de una clase
00:35:42
pero puedo implementar cuantas interfaces me da la gana y por lo tanto ya
00:35:46
Ya es suficiente como distinción para que existan las dos cosas, ¿vale?
00:35:50
Pero vamos a ver otras cosillas.
00:35:56
Si diferencian en propósito, ¿vale?
00:35:59
Una clase abstracta se utiliza para proporcionar una estructura básica para una jerarquía de clases,
00:36:03
mientras que una interfaz se utiliza para definir un contrato que debe cumplirse por una clase que implementa la interfaz.
00:36:11
O sea, cuando yo hago una clase abstracta y implemento esa clase abstracta, la estoy metiendo en mi jerarquía de herencia.
00:36:17
Es un anillo de mi jerarquía de herencia.
00:36:28
La interfaz no tiene nada que ver con mi herencia.
00:36:31
¿En qué sentido?
00:36:37
Yo puedo tener aquí mis instrumentos musicales y cosas por el estilo y puedo hacer que algunos de estos instrumentos musicales sean comparables.
00:36:38
Aquellos que quiero que sean comparables, implementarán la interfaz comparable.
00:36:47
Los que no tiene sentido que sean comparables, no la implementarán.
00:36:51
Pero eso es fuera de la estructura.
00:36:55
La estructura comparable no entra dentro de la jerarquía de herencia.
00:36:58
Es fuera, es otra cosa.
00:37:05
Entonces, la herencia me define la estructura de mis elementos,
00:37:08
mis entidades dentro de mi programa.
00:37:14
Entonces tengo persona, de persona heredada empleado, empleado tiene gerente, y de persona también alumno, y de empleado también profesor, qué sé yo. Y tengo mi estructura. Y luego, aparte, tendré mis, algunas de estas tendrán algunas interfaces, algunas de estas no, pero no son dentro de esta estructura jerárquica.
00:37:16
¿Sí? Cosa separada.
00:37:39
Implementación de métodos.
00:37:43
Una clase abstracta puede proporcionar una implementación para alguno de sus métodos,
00:37:45
mientras que la clase que la hereda anda debe implementar los métodos restantes.
00:37:49
Por otro lado, en una interfaz los métodos son solo declaraciones y no tienen una implementación,
00:37:54
a menos que no sean métodos default.
00:37:59
Esto es un poco tirar por los pelos.
00:38:00
Pero en general, una clase abstracta es una mezcla de abstracto y concreto,
00:38:03
una interfaz debería tender
00:38:09
al más abstracto posible
00:38:11
herencia
00:38:13
una clase puede extender
00:38:17
solo una clase abstracta mientras puedes hacer
00:38:20
múltiples interfaces, esto es lo que
00:38:22
hemos dicho al principio que es una de las cosas
00:38:24
más importantes, puedo
00:38:26
implementar cuantas interfaces quiero
00:38:28
extender una sola clase
00:38:29
y luego variables, esta es una cosa que no os he dicho
00:38:31
pero está por allí, dentro de una clase
00:38:34
abstracta yo puedo poner
00:38:36
variables
00:38:38
variables estáticas y no estáticas.
00:38:40
O sea, yo podía hacer dentro de figura número lados,
00:38:43
y luego número lados pertenece al objeto,
00:38:47
y cuando creo cuadrado, él tiene el campo número lados propio de ese objeto,
00:38:49
porque es un atributo del objeto, no de la clase.
00:38:56
Es no estático, no es estático.
00:38:59
¿Sí?
00:39:02
Sin embargo, en una interfaz no puedo poner variables no estáticas.
00:39:02
En una interfaz estoy forzado a poner o variables estáticas o finales, o sea, constantes.
00:39:11
En una interfaz no puede tener una variable del objeto.
00:39:19
Esto es una diferencia bastante importante.
00:39:25
si yo cuando creo, estoy pensando así
00:39:27
en hacer algo abstracto, que tenga métodos abstractos
00:39:30
y necesito ponerle un valor
00:39:32
a este objeto
00:39:35
que esté allí y que luego hereden
00:39:36
todos sus objetos, no puedo utilizar
00:39:38
una interfaz, tengo que utilizar una clase abstracta
00:39:40
y luego están cosas
00:39:44
malvadas
00:39:49
y muy muy muy complejas
00:39:51
¿Cómo son las interfaces funcionales?
00:39:54
Interfaz funcional es un monstruo de este tipo
00:40:00
Que me dice que hay ejecutar
00:40:02
Que hay una interfaz operación que tiene el método ejecutar
00:40:07
Y yo lo que hago es que cuando hago una operación como por ejemplo suma
00:40:11
Le paso aquí la definición de este ejecutar
00:40:16
Y entonces, luego, cuando uso suma, hago suma, ¿dónde está?
00:40:22
Suma punto ejecutar tres cinco, ejecutar tres cinco, aquí le he pasado la definición de qué tiene que hacer.
00:40:29
Es decir, que no le estoy pasando un valor, me lo estoy pasando una función.
00:40:39
Y esto gracias a mi amigo lambda cálculo.
00:40:46
No.
00:40:55
Es como si tú tuvieras un math.hazalgo
00:40:59
y antes de utilizar el math.hazalgo
00:41:01
le definas qué tiene que hacer.
00:41:04
Le dices, recibirás dos parámetros, a y b,
00:41:07
y lo que tienes que devolver,
00:41:11
y aquí te haces tú el cálculo para calcular la potencia.
00:41:12
Entonces te calcula la potencia cuando dices haz algo.
00:41:16
Si en vez le defines la suma,
00:41:18
cuando dice haz algo, pues te hará la suma.
00:41:20
Si le pasas como definición.
00:41:22
la función que tú quieras
00:41:25
él en automático hará esa cosa
00:41:28
pero son cosas
00:41:30
complejas
00:41:32
existen
00:41:33
y si usáis chat GPT
00:41:35
lo veis esta cosa aquí, la flecha
00:41:37
cuando veis la flecha, tremblad
00:41:40
¿os acordáis al principio de clase
00:41:42
de este curso
00:41:48
cuando todavía erais pequeños
00:41:49
y yo os hablaba
00:41:51
de distintos
00:41:54
tipos de lenguajes
00:41:56
yo os decía que hay los lenguajes
00:41:58
imperativos y nosotros vamos a trabajar
00:41:59
con lenguajes imperativos y luego hay los
00:42:02
lenguajes funcionales
00:42:04
y los lenguajes lógicos
00:42:06
¿sí?
00:42:08
como Prolog, Lisp
00:42:10
pues esto
00:42:11
es
00:42:15
intento de hacer en Java
00:42:17
que es imperativo
00:42:20
cosas de lenguaje
00:42:21
funcional
00:42:24
Como los lenguajes funcionales algún tipo de problema lo solucionan mucho más rápidamente
00:42:24
Mucho más eficientemente que la programación imperativa
00:42:34
Pues lo que ha hecho Java en las últimas versiones
00:42:37
Es introducir una posibilidad de usar un pseudo lenguaje funcional
00:42:41
Dentro del marco del lenguaje imperativo que es Java
00:42:47
En lenguaje funcional se basa sobre el concepto que tú puedes pasar como parámetros funciones
00:42:51
Porque esto de aquí son directivas al precompilador
00:42:58
Para que el precompilador sabe que esta no es una interfaz normal
00:43:16
Es una interfaz que da dolor de cabeza a los estudiantes
00:43:20
Y esto es todo lo que veremos de la interfaz funcional
00:43:24
Claramente caerá en el examen porque somos malvados
00:43:31
dudas
00:43:34
- Materias:
- Programación
- Niveles educativos:
- ▼ Mostrar / ocultar niveles
- Formación Profesional
- Ciclo formativo de grado superior
- Primer Curso
- Autor/es:
- Stefano Chiesa
- Subido por:
- Stefano C.
- Licencia:
- Reconocimiento - No comercial
- Visualizaciones:
- 16
- Fecha:
- 21 de enero de 2025 - 12:39
- Visibilidad:
- Clave
- Centro:
- IES ROSA CHACEL
- Duración:
- 43′ 41″
- Relación de aspecto:
- 16:10 El estándar usado por los portátiles de 15,4" y algunos otros, es ancho como el 16:9.
- Resolución:
- 1152x720 píxeles
- Tamaño:
- 106.55 MBytes