Interfaces
Interfaces
Interfaces
Una clase abstracta es una clase que no va tener instancias. En Java hay un mecanismo del
lenguaje que permite declarar que una clase sea abstracta, y el compilador garantiza que no va
a existir ninguna instancia.
Método abstracto: se declara pero no se define, es decir, no tiene código. Esto sirve para
forzar que en las subclases se defina como corresponda.
Tip: La idea es que cualquier clase con algún método abstracto sea abstracta.
Polimorfismo Y Tipos
la capacidad de que existan métodos distintos con el mismo nombre (en distintas
clases)
Lo más valioso que nos brinda la idea de polimorfismo es que al enviar un mensaje puede
que no sepa, y en principio no me debería importar, qué objeto va a terminar respondiendo
a dicho mensaje.
Porque me permite extender la aplicación y una vez más, el código cliente, es decir, el código
que utiliza los objetos polimórficos no va a verse afectado.
Veamos un ejemplo:
En el siguiente ejemplo, vemos la clase abstracta Animal que define el método abstracto
desplazar y dos clases concretas: Perro y Gato.
Si en un futuro (no muy lejano) necesito agregar otras subclases supongamos Canguro,
Canario, Hamster, nuestro código cliente, en este caso el método Paseador::pasear no se vería
afectado.
En Java, como en todo lenguaje tipado, el tipo de cada objeto debe ser declarado de forma
explícita. Por ahora, el tipo de cada objeto es su clase, y la relación de supertipo/subtipo está
dada por la jerarquía de herencia. Por eso donde declaramos que pasa un Animal podemos
hacer pasar un Perro o un Canguro. Por un lugar donde declaro un parámtro de una
determinada clase, puede pasar una instancia de esa clase, o de cualquier subclase. En el
ejemplo: donde declaro un parámetro de tipo Animal, puede pasar un Perro o un Canguro, pero
no puede pasar una Manada porque no se encuentra en la jerarquía de clases definida.
Interfaces
¿Qué es una interface?
Volvamos al ejemplo anterior, donde aparece la clase Manada. Lo que necesitamos es que el
código en la clase Paseador pueda compilar y funcionar.
Una opción es agregar en la jerarquía de herencia las clases Animal y Manada, haciendo que
alguna sea descendiente de la otra. El problema de esta solución es que además de ser poco
natural, podemos tener el problema que una Manada entiende mensajes que aplicados a un
Animal no tiene sentido (ej. cantidad de integrantes) y viceversa (ej. la edad).
Otra solución sería agregar una superclase que sólo tenga métodos comunes a ambas clases
(Animal y Manada). Supongamos que sólo tienen en común el método desplazar
Con esta solución, el método Paseador::pasear podría recibir un objeto de tipo SerVivo y
funcionaría de forma correcta.
En este caso vemos que la clase SerVivo es puramente abstracta, es decir, sus métodos son
todos abstractos. En lenguajes tipados como Java, existe otra forma de resolver esta situación
a través del concepto de interfaces.
Son tipos, o sea que se pueden declarar variables de tipo interface, y parámetros de tipo
interface, y el tipo de retorno de un método puede ser una interface. Pero no están en la
jerarquía de herencia de clases.
A diferencia de la herencia de clases, donde una clase extiende a otra, con las interfaces se
dice que una clase implementa una interfaz.
Otra diferencia entre el uso de herencia e interfaces, es que en Java no podemos tener
herencia múltiple, es decir, heredar (extender) de varias clases, pero sí podemos implementar
varias interfaces.
Para resolver este nuevo problema, la solución de una superclase no sería viable, por lo que
vamos a recurrir al uso de interfaces. Nuestro nuevo diagrama de clases quedaria de la
siguiente manera:
Con el diagrama de clases anterior, podemos ver que el método Paseador::pasear funciona
tanto si recibe un animal cualquiera como una manada. Otra ventaja es que no forzamos a la
clase Canario a implementar métodos que no le corresponde.
Pensando en el método Paseador::pasear ahora puedo pasarle por parámetro cualquier objeto
que implemente la interfaz SerVivo, lo que me permite agregar clases a mi solución a futuro,
siempre y cuando implementen dicha interfaz.
Pensemos que sin interfaces, estaríamos forzando a que los objetos que recibe el método
Paseador::pasear debe estar dentro de la jerarquía de Animal, podría ser Gato, Perro pero no
podría ser Manada; lo que nos llevaría al problema inicial.
Con interfaces, elimino dicha limitación. Ahora el método a ser invocado no tiene ninguna
limitación relacionada con la jerarquía de herencia de clases. Alcanza con que el método esté
en una clase que implementa la interface SerVivo, y esas clases pueden estar en cualquier
lado. Las interfaces son tipos y desde este punto de vista lo que estoy logrando es que un
objeto tenga muchos tipos, que en un lenguaje tipado es lo que me permite que lo use en más
contextos.