Implementando Interfaces
Decíamos con anterioridad que las interfaces son una especie de «contrato», una declaración del conjunto de métodos que podemos utilizar si una clase implementa dicha interfaz.
Por tanto, una clase al implementar una interfaz debe definir cada uno de los métodos de ésta. De esta forma, cualquier persona que instancie un objeto de la clase implementadora tiene la seguridad de que puede llamar a los métodos de la interfaz.
Cuando Java encuentra una clase que dice implementar una interfaz la comprueba. Si falta algún método por definir nos dará error de compilación. Basta que tengamos la definición de los métodos aunque no tengamos ningún código para ellos.
Por ejemplo, esta clase no daría ningún error:
public interface Cultivable{ public void plantar(); public void regar(); public int cosechar(); } public class cultivoFresas implements Cultivable { .... public void plantar() {} public void regar(){} public int cosechar(){} ... }
También es posible que nuestra clase implementadora sea abstracta. En este caso la clase puede elegir entre implementar algunos métodos, todos o ninguno. Y sería alguna clase concreta de ésta la que defina los restantes.
Por ejemplo:
public abstract class Cultivos implements Cultivable { public void plantar() { ... } //Ejemplo de clase abstracta public void regar() { ... } // que define algunos métodos } public class Maiz extends Cultivos { public void int cosechar() { ... } //Y el que falta en la concreta. }
Las clases que implementan una interfaz deben seguir las misas normas que las clases que extienden una clase abstracta:
- Deben definir todos los métodos de la interfaz.
- Seguir todas las normas para las sobrescrituras (overrides).
- Declarar sólo las excepciones comprobadas definidas en la interfaz o subclases de éstas.
- Mantener la signatura de los métodos y el tipo devuelto (o un subtipo de éste).
Hay que recordar también que:
- Una clase puede extender a sólo una clase.
- Una clase puede implementar varias interfaces.
- Una interfaz puede extender una o varias interfaces, pero nunca puede implementar.
Tipos de Retorno Legales
Vamos a hacer un pequeño resumen de qué podemos declarar como tipos de retorno:
- Métodos sobrecargados: un método sobrecargado es un método totalmente diferente y nuevo.
Si tenemos un método en una clase y lo sobrecargamos en una subclase no tiene que regirse por las normas de los métodos sobrescritos. Podemos declarar cualquier tipo de retorno.Hay que recordar que la sobrecarga no sólo se puede basar en un tipo diferente de retorno, debía diferenciarse del método original por el número o tipo de parámetros.
- Métodos sobrescritos: un método sobrescrito consistía en dar una implementación distinta a un método en una subclase. El método debía coincidir exactamente. A partir de Java 5, se permite también que el tipo de retorno en el método sobrescrito sea una subclase del tipo de retorno del método en la superclase.
Para devolver correctamente un valor para que se ajuste al tipo de retorno, hay que tener en cuenta:
- Sólo podemos devolver null si el tipo de retorno es una variable de referencia (objeto y no tipo primitivo).
- Si el tipo de retorno es un tipo primitivo cualquier valor que sea del tipo o que se pueda convertir
implícitamente o explícitamente (usando un cast).
- Nunca retornar un valor si el tipo de retorno es void.
- Si el tipo de retorno es una variable de referencia (objeto y no tipo primitivo) podemos devolver un objeto de una subclase, ya que se hace el cast implícitamente.
- Si el tipo de retorno es una interfaz podemos devolver cualquier objeto de una clase que implemente dicha interfaz.