En una de mis entrevistas, me han pedido que explique la diferencia entre una Interfaz y una Clase abstracta.
Esta es mi respuesta:
Los métodos de una interfaz Java son implícitamente abstractos y no pueden tener implementaciones. Una clase abstracta de Java puede tener métodos de instancia que implementan un comportamiento por defecto.
Las variables declaradas en una interfaz Java son, por defecto, finales. Una clase abstracta clase abstracta puede contener variables no finales.
Los miembros de una interfaz Java son públicos por defecto. Una clase abstracta de Java puede tener los sabores habituales de los miembros de la clase como private protected, etc.
Una interfaz Java debe ser implementada usando la palabra clave "implements". Una clase abstracta Java debe ser extendida usando la palabra clave "extends".
Una interfaz sólo puede extender otra interfaz Java, una clase abstracta puede extender otra clase Java e implementar múltiples interfaces Java.
Una clase Java puede implementar múltiples interfaces pero sólo puede extender una clase abstracta.
Sin embargo, el entrevistador no estaba satisfecho, y me dijo que esta descripción representaba "Conocimiento de libro*".
Me pidió una respuesta más práctica, explicando cuándo elegiría una clase abstracta en lugar de una interfaz, utilizando ejemplos prácticos.
¿En qué me equivoqué?
Nada es perfecto en este mundo. Es posible que esperaran un enfoque más práctico.
Pero después de su explicación podría añadir estas líneas con un enfoque ligeramente diferente.
Las interfaces son reglas (reglas porque hay que darles una implementación que no se puede ignorar o evitar, por lo que se imponen como reglas) que funcionan como un documento de entendimiento común entre varios equipos en el desarrollo de software.
Las interfaces dan la idea de lo que hay que hacer, pero no de cómo se va a hacer. Así que la implementación depende completamente del desarrollador siguiendo las reglas dadas (es decir, la firma de los métodos).
Las clases abstractas pueden contener declaraciones abstractas, implementaciones concretas o ambas.
Las declaraciones abstractas son como reglas a seguir y las implementaciones concretas son como directrices (puedes usarla tal cual o puedes ignorarla anulándola y dándole tu propia implementación).
Además, los métodos con la misma firma que pueden cambiar el comportamiento en diferentes contextos se proporcionan como declaraciones de interfaz como reglas para implementar en consecuencia en diferentes contextos.
Editar: Java 8 facilita la definición de métodos por defecto y estáticos en la interfaz.
public interface SomeInterfaceOne {
void usualAbstractMethod(String inputString);
default void defaultMethod(String inputString){
System.out.println("Inside SomeInterfaceOne defaultMethod::"+inputString);
}
}
Ahora cuando una clase implementa SomeInterface, no es obligatorio proporcionar la implementación de los métodos por defecto de la interfaz.
Si tenemos otra interfaz con los siguientes métodos:
public interface SomeInterfaceTwo {
void usualAbstractMethod(String inputString);
default void defaultMethod(String inputString){
System.out.println("Inside SomeInterfaceTwo defaultMethod::"+inputString);
}
}
Java no permite extender múltiples clases porque resulta en el "Problema del Diamante " donde el compilador no es capaz de decidir qué método de la superclase usar. Con los métodos por defecto, el problema del diamante surgirá también para las interfaces. Porque si una clase implementa tanto
SomeInterfaceOne and SomeInterfaceTwo
y no implementa el método común por defecto, el compilador no puede decidir cuál elegir. Para evitar este problema, en java 8 es obligatorio implementar métodos comunes por defecto de diferentes interfaces. Si una clase implementa ambas interfaces, tiene que proporcionar la implementación del método defaultMethod(), de lo contrario el compilador lanzará un error en tiempo de compilación.
Tu explicación parece decente, pero puede parecer que lo has leído todo de un libro de texto... :-/
Lo que más me preocupa es, ¿cómo de sólido era tu ejemplo? ¿Te has molestado en incluir casi todas las diferencias entre abstracto e interfaces?
Personalmente, sugeriría este enlace: http://mindprod.com/jgloss/interfacevsabstract.html#TABLE
para una lista exhaustiva de diferencias..
Espero que te ayude a ti y a todos los demás lectores en sus futuras entrevistas
Una interfaz es un "contrato" donde la clase que implementa el contrato promete implementar los métodos. Un ejemplo en el que tuve que escribir una interfaz en lugar de una clase fue cuando estaba actualizando un juego de 2D a 3D. Tuve que crear una interfaz para compartir clases entre la versión 2D y 3D del juego.
package adventure;
import java.awt.*;
public interface Playable {
public void playSound(String s);
public Image loadPicture(String s);
}
Entonces puedo implementar los métodos basados en el entorno, sin dejar de ser capaz de llamar a esos métodos desde un objeto que no sabe qué versión del juego que está cargando.
public class Adventure extends JFrame implements Playable
Public class Dungeon3D extends SimpleApplication implements Playable
Public class Main extends SimpleApplication implements AnimEventListener, ActionListener, Playable`
Típicamente, en el mundo del juego, el mundo puede ser una clase abstracta que realiza métodos en el juego:
public abstract class World...
public Playable owner;
public Playable getOwner() {
return owner;
}
public void setOwner(Playable owner) {
this.owner = owner;
}