Java 8 ha hecho cambios en las interfaces, las que ahora podemos agregarles métodos default (default methods). Esto permite agregar métodos a las interfaces sin necesidad de implementarlos en las clases hijas.
Este método default provee un comportamiento por defecto para el caso en que la clase concreta no lo especifique.
Método Default:
Sabemos que si definimos una interfaz y luego la modificamos agregando un nuevo método ‘romperemos’ todas las implementaciones y estaremos obligados a definir este nuevo método en las todas sus clases.
Por ejemplo tenemos nuestra interfaz y nuestra clase de este modo:
interface InterfaceA {
public void doSomething();
}
public class MyImpl implements InterfaceA {
@Override
public void doSomething() {
System.out.println("Hello");
}
}
Luego agregamos a nuestra interfaz otro método “doMore()” sabemos que estaremos obligados a implemetar ese nuevo método en MyImpl;
interface InterfaceA {
public void doSomething();
public void doMore();
}
public class MyImpl implements InterfaceA {
@Override
public void doSomething() {
System.out.println("Hello");
}
public void doMore() {
System.out.println("Hi");
}
}
Con Java 8 podemos definir un default method con implementación en la misma interfaz y que será utilizada por defecto si no se especifica en la clase concreta. Ya no estamos obligados a definirlo en MyImpl
interface InterfaceA {
public void doSomething();
default public void doMore() {
System.out.println("Hi");
}
}
public class MyImpl implements InterfaceA {
@Override
public void doSomething() {
System.out.println("Hello");
}
// esta clase ha 'heredado' el metodo default doMore()
}
Dos interfaces con el mismo método default:
Podemos encontrarnos con dos Intefaces con el mismo método default, en este caso si una clase implementa ambas interfaces deberemos proveer la implementación de este método en la clase concreta para evitar esta exception “MyImpl inherits unrelated defaults”
Java no tiene modo de saber qué método ejecutar, el de la InterfaceA o el de InterfaceB, por lo que debemos obligadamente implementarlo en la clase MyImpl.
interface InterfaceA {
public void doSomething();
default public void doMore() {
System.out.println("Hi from A");
}
}
interface InterfaceB {
default public void doMore() {
System.out.println("Hi from B");
}
}
public class MyImpl implements InterfaceA, InterfaceB {
@Override
public void doSomething() {
System.out.println("Hello");
}
public void doMore() {
System.out.println("Hi from Class ");
}
}
Invocar al método default desde la clase concreta:
Podríamos invocar desde la clase concreta MyImpl el método default de alguna de las interfaces de este modo.
public class MyImpl implements InterfaceA, InterfaceB {
@Override
public void doSomething() {
System.out.println("Hello");
}
public void doMore() {
InterfaceB.super.doMore();
}
}
Conclusión:
Podemos agregar default methods a la interfaz sin afectar las clases concretas que la implementan. Una implementación puede sobrescribir el método default. En el caso de ambigüedad, cuando hay dos interfaces con el mismo método la clase estará obligada a sobrescribir dicho método.