¿Cómo debería haber explicado la diferencia entre una interfaz y una clase abstracta?

En una de mis entrevistas, me pidieron que explicara la diferencia entre una interfaz y una clase abstracta .

Aquí está 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 implemente un comportamiento predeterminado.

Las variables declaradas en una interfaz Java son predeterminadas por defecto. Una 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 privado, protegido, etc.

Una interfaz Java debe implementarse utilizando la palabra clave “implements”; Una clase abstracta de Java debería extenderse usando la palabra clave “extends”.

Una interfaz puede ampliar solo 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 puede extender solo una clase abstracta.

Sin embargo, el entrevistador no estaba satisfecho, y me dijo que esta descripción representaba ” conocimiento libreco “.

Me pidió una respuesta más práctica, explicando cuándo elegiría una clase abstracta sobre una interfaz, usando ejemplos prácticos .

¿Qué hice mal?

Primero te daré un ejemplo:

public interface LoginAuth{ public String encryptPassword(String pass); public void checkDBforUser(); } 

Ahora supongamos que tiene 3 bases de datos en su aplicación. Entonces, todas y cada una de las implementaciones para esa base de datos deben definir los 2 métodos anteriores:

 public class DBMySQL implements LoginAuth{ // Needs to implement both methods } public class DBOracle implements LoginAuth{ // Needs to implement both methods } public class DBAbc implements LoginAuth{ // Needs to implement both methods } 

Pero, ¿qué ocurre si encryptPassword () no depende de la base de datos, y es igual para cada clase? Entonces lo anterior no sería un buen enfoque.

En cambio, considere este enfoque:

 public abstract class LoginAuth{ public String encryptPassword(String pass){ // Implement the same default behavior here // that is shared by all subclasses. } // Each subclass needs to provide their own implementation of this only: public abstract void checkDBforUser(); } 

Ahora, en cada clase secundaria, solo necesitamos implementar un método: el método que depende de la base de datos.

Intenté hacerlo lo mejor posible y espero que esto aclare tus dudas.

Nada es perfecto en este mundo. Es posible que hayan estado esperando un enfoque más práctico.

Pero después de su explicación, puede agregar estas líneas con un enfoque ligeramente diferente.

  1. Las interfaces son reglas (reglas porque debe darles una implementación que no pueden ignorar o evitar, de modo que se impongan como reglas) que funciona como un documento de entendimiento común entre varios equipos en el desarrollo de software.

  2. Las interfaces le dan a la idea lo que se debe hacer pero no cómo se hará. Entonces la implementación depende completamente del desarrollador al seguir las reglas dadas (significa la firma de métodos dada).

  3. Las clases abstractas pueden contener declaraciones abstractas, implementaciones concretas o ambas.

  4. Las declaraciones abstractas son como las reglas que deben seguirse y las implementaciones concretas son como pautas (puede usarlo tal cual o puede ignorarlo redefiniendo y dándole su propia implementación).

  5. Además, qué métodos con la misma firma 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 predeterminados 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 implemente SomeInterface, no es obligatorio proporcionar implementación para los métodos de interfaz predeterminados.

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 da como resultado el “Problema Diamante” donde el comstackdor no puede decidir qué método de superclase usar. Con los métodos predeterminados, también surgirá el problema del diamante para las interfaces. Porque si una clase está implementando ambos

 SomeInterfaceOne and SomeInterfaceTwo 

y no implementa el método predeterminado común, el comstackdor 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 cualquier clase está implementando las dos interfaces anteriores, tiene que proporcionar la implementación del método defaultMethod (), de lo contrario el comstackdor lanzará un error de tiempo de comstackción.

Hiciste un buen resumen de las diferencias prácticas en el uso y la implementación, pero no dijo nada sobre la diferencia en el significado.

Una interfaz es una descripción del comportamiento que tendrá una clase implementadora. La clase de implementación garantiza que tendrá estos métodos que se pueden usar en él. Básicamente es un contrato o una promesa que la clase tiene que hacer.

Una clase abstracta es una base para diferentes subclases que comparten un comportamiento que no necesita ser creado repetidamente. Las subclases deben completar el comportamiento y tener la opción de anular el comportamiento predefinido (siempre que no se defina como final o private ).

Encontrará buenos ejemplos en el paquete java.util que incluye interfaces como List y clases abstractas como AbstractList que ya implementa la interfaz. La documentación oficial describe AbstractList siguiente manera:

Esta clase proporciona una implementación esquemática de la interfaz List para minimizar el esfuerzo requerido para implementar esta interfaz respaldada por un almacén de datos de “acceso aleatorio” (como una matriz).

Una interfaz consiste en variables singleton (final estático público) y métodos abstractos públicos. Normalmente preferimos usar una interfaz en tiempo real cuando sabemos qué hacer, pero no sabemos cómo hacerlo .

Este concepto se puede entender mejor con el ejemplo:

Considere una clase de pago. El pago se puede realizar de muchas maneras, como PayPal, tarjeta de crédito, etc. Por lo tanto, normalmente tomamos Pago como nuestra interfaz que contiene un método makePayment() y CreditCard y PayPal son las dos clases de implementación.

 public interface Payment { void makePayment();//by default it is a abstract method } public class PayPal implements Payment { public void makePayment() { //some logic for PayPal payment //eg Paypal uses username and password for payment } } public class CreditCard implements Payment { public void makePayment() { //some logic for CreditCard payment //eg CreditCard uses card number, date of expiry etc... } } 

En el ejemplo anterior, CreditCard y PayPal son dos clases / estrategias de implementación. Una interfaz también nos permite el concepto de herencia múltiple en Java que no puede lograrse mediante una clase abstracta.

Elegimos una clase abstracta cuando hay algunas funciones para las que sabemos qué hacer, y otras características que sabemos cómo realizar .

Considere el siguiente ejemplo:

 public abstract class Burger { public void packing() { //some logic for packing a burger } public abstract void price(); //price is different for different categories of burgers } public class VegBerger extends Burger { public void price() { //set price for a veg burger. } } public class NonVegBerger extends Burger { public void price() { //set price for a non-veg burger. } } 

Si agregamos métodos (concretos / abstractos) en el futuro a una clase abstracta dada, entonces la clase de implementación no necesitará cambiar su código. Sin embargo, si agregamos métodos en una interfaz en el futuro, debemos agregar implementaciones a todas las clases que implementaron esa interfaz; de lo contrario, se producirán errores de tiempo de comstackción.

Existen otras diferencias, pero estas son las principales que pudieron haber sido las que esperaba su entrevistador. Espero que esto haya sido útil.

Todas sus declaraciones son válidas, excepto su primera statement (después del lanzamiento de Java 8):

Los métodos de una interfaz Java son implícitamente abstractos y no pueden tener implementaciones

Desde la página de documentación:

Una interfaz es un tipo de referencia, similar a una clase, que puede contener solo constantes, firmas de métodos, métodos predeterminados, métodos estáticos y tipos nesteds

Los cuerpos de método existen solo para métodos predeterminados y métodos estáticos.

Métodos predeterminados:

Una interfaz puede tener métodos predeterminados , pero son diferentes a los métodos abstractos en clases abstractas.

Los métodos predeterminados le permiten agregar nuevas funcionalidades a las interfaces de sus bibliotecas y garantizar la compatibilidad binaria con el código escrito para versiones anteriores de esas interfaces.

Cuando extiende una interfaz que contiene un método predeterminado, puede hacer lo siguiente:

  1. No mencione el método predeterminado en absoluto, lo que permite que su interfaz extendida herede el método predeterminado.
  2. Redeclare el método predeterminado, lo que lo hace abstract .
  3. Redefina el método predeterminado, que lo reemplaza.

Métodos estáticos:

Además de los métodos predeterminados, puede definir métodos estáticos en las interfaces. (Un método estático es un método que está asociado con la clase en la que se define en lugar de con cualquier objeto. Cada instancia de la clase comparte sus métodos estáticos).

Esto facilita la organización de métodos de ayuda en sus bibliotecas;

Código de ejemplo de la página de documentación sobre la interface tiene métodos static y default .

 import java.time.*; public interface TimeClient { void setTime(int hour, int minute, int second); void setDate(int day, int month, int year); void setDateAndTime(int day, int month, int year, int hour, int minute, int second); LocalDateTime getLocalDateTime(); static ZoneId getZoneId (String zoneString) { try { return ZoneId.of(zoneString); } catch (DateTimeException e) { System.err.println("Invalid time zone: " + zoneString + "; using default time zone instead."); return ZoneId.systemDefault(); } } default ZonedDateTime getZonedDateTime(String zoneString) { return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString)); } } 

Use las pautas a continuación para elegir si usar una interfaz o clase abstracta.

Interfaz:

  1. Para definir un contrato (preferiblemente sin estado, quiero decir sin variables)
  2. Para vincular clases no relacionadas con tiene una capacidad.
  3. Para declarar variables constantes públicas ( estado inmutable )

Clase abstracta:

  1. Compartir código entre varias clases estrechamente relacionadas. Establece es una relación.

  2. Compartir estado común entre clases relacionadas (el estado puede modificarse en clases concretas)

Artículos Relacionados:

Interfaz vs clase abstracta (OO general)

Implementos vs extends: ¿Cuándo usar? ¿Cual es la diferencia?

Al repasar estos ejemplos, puedes entender que

Las clases no relacionadas pueden tener capacidades a través de la interfaz, pero las clases relacionadas cambian el comportamiento a través de la extensión de las clases base.

Diferencia entre la clase Abstact y la interfaz

  1. Clases abstractas versus interfaces en Java 8
  2. Diferencia conceptual:

Métodos predeterminados de interfaz en Java 8

  1. ¿Cuál es el método predeterminado?
  2. Para cada error de comstackción de método resuelto usando el método predeterminado
  3. Método predeterminado y problemas de ambigüedad de herencia múltiple
  4. Puntos importantes sobre los métodos predeterminados de la interfaz de Java:

Método estático de la interfaz de Java

  1. Método estático de la interfaz Java, ejemplo de código, método estático vs método predeterminado
  2. Puntos importantes sobre el método estático de la interfaz de Java:

Interfaces funcionales de Java



Clases abstractas versus interfaces en Java 8

Los cambios de la interfaz Java 8 incluyen métodos estáticos y métodos predeterminados en las interfaces. Antes de Java 8, solo podíamos tener declaraciones de métodos en las interfaces. Pero desde Java 8, podemos tener métodos predeterminados y métodos estáticos en las interfaces.

Después de presentar el Método predeterminado, parece que las interfaces y las clases abstractas son las mismas. Sin embargo, todavía son un concepto diferente en Java 8.

La clase abstracta puede definir constructor. Están más estructurados y pueden tener un estado asociado a ellos. Mientras que, por el contrario, el método predeterminado puede implementarse solo en términos de invocación de otros métodos de interfaz, sin referencia al estado de una implementación en particular. Por lo tanto, ambos usan para diferentes propósitos y elegir entre dos realmente depende del contexto del escenario.

Diferencia conceptual:

Las clases abstractas son válidas para implementaciones esqueléticas (es decir, parciales) de interfaces, pero no deberían existir sin una interfaz correspondiente.

Entonces, cuando las clases abstractas se reducen de manera efectiva para que sean implementaciones esquemáticas de interfaces de baja visibilidad, ¿pueden los métodos predeterminados eliminar esto también? Decididamente: ¡No! La implementación de interfaces casi siempre requiere algunas o todas las herramientas de construcción de clases que carecen los métodos predeterminados. Y si alguna interfaz no lo hace, es claramente un caso especial, que no debe desviarse.

Métodos predeterminados de interfaz en Java 8

Java 8 introduce la nueva característica ” Método predeterminado ” o (métodos Defender), que permite al desarrollador agregar nuevos métodos a las interfaces sin romper la implementación existente de esta interfaz. Proporciona flexibilidad para permitir la implementación de la definición de la interfaz que se utilizará como predeterminada en la situación en que una Clase concreta no proporcione una implementación para ese método.

Consideremos un pequeño ejemplo para entender cómo funciona:

 public interface OldInterface {    public void existingMethod();    default public void newDefaultMethod() {        System.out.println("New default method"               + " is added in interface");    } } 

La siguiente clase se comstackrá correctamente en Java JDK 8,

 public class OldInterfaceImpl implements OldInterface {    public void existingMethod() {     // existing implementation is here…    } } 

Si crea una instancia de OldInterfaceImpl:

 OldInterfaceImpl obj = new OldInterfaceImpl (); // print “New default method add in interface” obj.newDefaultMethod(); 

Método predeterminado:

Los métodos predeterminados nunca son definitivos, no se pueden sincronizar y no pueden anular los métodos de Object. Siempre son públicos, lo que limita severamente la capacidad de escribir métodos cortos y reutilizables.

Se pueden proporcionar métodos predeterminados a una interfaz sin afectar las clases de implementación, ya que incluye una implementación. Si cada método agregado en una interfaz se define con la implementación, entonces no se ve afectada la implementación de la clase. Una Clase implementadora puede anular la implementación predeterminada proporcionada por la Interfaz.

Los métodos predeterminados permiten agregar nuevas funcionalidades a las interfaces existentes sin interrumpir la implementación anterior de estas interfaces.

Cuando ampliamos una interfaz que contiene un método predeterminado, podemos realizar lo siguiente,

  1. No anule el método predeterminado y heredará el método predeterminado.
  2. Reemplaza el método predeterminado similar a otros métodos que anulamos en la subclase.
  3. Redeclare el método predeterminado como abstracto, lo que fuerza a la subclase a anularlo.

Para cada error de comstackción de método resuelto usando el método predeterminado

Para Java 8, las colecciones JDK se han ampliado y para cada método se agrega a la colección completa (que funciona junto con lambdas). De manera convencional, el código se ve a continuación,

 public interface Iterable {    public void forEach(Consumer consumer); } 

Debido a esto, cada clase implementadora con errores de comstackción, por lo tanto, se agrega un método predeterminado con una implementación requerida para que la implementación existente no se modifique.

La interfaz Iterable con el método predeterminado está debajo,

 public interface Iterable {    public default void forEach(Consumer                    consumer) {        for (T t : this) {            consumer.accept(t);        }    } } 

El mismo mecanismo se ha utilizado para agregar Stream en la interfaz JDK sin romper las clases de implementación.


Método predeterminado y problemas de ambigüedad de herencia múltiple

Dado que Java Class puede implementar múltiples interfaces y cada interfaz puede definir el método predeterminado con la misma firma de método, por lo tanto, los métodos heredados pueden entrar en conflicto entre sí.

Considere el siguiente ejemplo,

 public interface InterfaceA {       default void defaultMethod(){           System.out.println("Interface A default method");    } } public interface InterfaceB {   default void defaultMethod(){       System.out.println("Interface B default method");   } } public class Impl implements InterfaceA, InterfaceB { } 

El código anterior no se comstackrá con el siguiente error,

java: la clase Impl hereda los valores predeterminados no relacionados para defaultMethod () de los tipos InterfaceA e InterfaceB

Para solucionar esta clase, debemos proporcionar la implementación del método predeterminado:

 public class Impl implements InterfaceA, InterfaceB {    public void defaultMethod(){    } } 

Además, si queremos invocar la implementación predeterminada proporcionada por cualquiera de Super Interface en lugar de nuestra propia implementación, podemos hacerlo de la siguiente manera:

 public class Impl implements InterfaceA, InterfaceB {    public void defaultMethod(){        // existing code here..        InterfaceA.super.defaultMethod();    } } 

Podemos elegir cualquier implementación predeterminada o ambas como parte de nuestro nuevo método.

Puntos importantes sobre los métodos predeterminados de la interfaz de Java:

  1. Los métodos por defecto de la interfaz de Java nos ayudarán a ampliar las interfaces sin tener miedo de romper las clases de implementación.
  2. Los métodos por defecto de la interfaz Java han reducido las diferencias entre las interfaces y las clases abstractas.
  3. Los métodos por defecto de la interfaz Java 8 nos ayudarán a evitar las clases de utilidad, como que todo el método de clase Colecciones se puede proporcionar en las interfaces en sí.
  4. Los métodos por defecto de la interfaz de Java nos ayudarán a eliminar las clases de implementación base, podemos proporcionar una implementación predeterminada y las clases de implementación pueden elegir cuál anular.
  5. Una de las principales razones para introducir métodos predeterminados en las interfaces es mejorar la API de colecciones en Java 8 para admitir expresiones lambda.
  6. Si alguna clase en la jerarquía tiene un método con la misma firma, los métodos predeterminados se vuelven irrelevantes. Un método predeterminado no puede anular un método de java.lang.Object. El razonamiento es muy simple, es porque Object es la clase base para todas las clases de Java. Entonces, incluso si tenemos métodos de clase Object definidos como métodos predeterminados en las interfaces, será inútil porque siempre se usará el método de la clase Object. Es por eso que para evitar confusiones, no podemos tener métodos predeterminados que estén anulando los métodos de la clase Object.
  7. Los métodos predeterminados de la interfaz de Java también se conocen como métodos Defender o métodos de extensión virtual.

Enlace de recursos:

  1. Interfaz con métodos predeterminados vs Clase abstracta en Java 8
  2. Clase abstracta versus interfaz en la era JDK 8
  3. Evolución de la interfaz a través de métodos de extensión virtual

Método estático de la interfaz de Java

Método estático de la interfaz Java, ejemplo de código, método estático vs método predeterminado

El método estático de la interfaz Java es similar al método predeterminado, excepto que no podemos anularlos en las clases de implementación. Esta característica nos ayuda a evitar resultados no deseados en caso de implementación deficiente en las clases de implementación. Veamos esto con un simple ejemplo.

 public interface MyData { default void print(String str) { if (!isNull(str)) System.out.println("MyData Print::" + str); } static boolean isNull(String str) { System.out.println("Interface Null Check"); return str == null ? true : "".equals(str) ? true : false; } } 

Ahora veamos una clase de implementación que está teniendo el método isNull () con una implementación deficiente.

 public class MyDataImpl implements MyData { public boolean isNull(String str) { System.out.println("Impl Null Check"); return str == null ? true : false; } public static void main(String args[]){ MyDataImpl obj = new MyDataImpl(); obj.print(""); obj.isNull("abc"); } } 

Tenga en cuenta que isNull (String str) es un método de clase simple, no está anulando el método de interfaz. Por ejemplo, si añadiremos la anotación @Override al método isNull (), dará como resultado un error de comstackción.

Ahora cuando ejecutaremos la aplicación, obtenemos la siguiente salida.

Interfaz de verificación nula

Impl Null Check

Si hacemos que el método de interfaz sea estático a predeterminado, obtendremos el siguiente resultado.

Impl Null Check

MyData Print ::

Impl Null Check

El método estático de la interfaz Java solo es visible para los métodos de interfaz, si eliminamos el método isNull () de la clase MyDataImpl, no podremos usarlo para el objeto MyDataImpl. Sin embargo, al igual que otros métodos estáticos, podemos usar métodos estáticos de interfaz utilizando el nombre de clase. Por ejemplo, una statement válida será:

 boolean result = MyData.isNull("abc"); 

Puntos importantes sobre el método estático de la interfaz de Java:

  1. El método estático de la interfaz de Java es parte de la interfaz, no podemos usarlo para los objetos de la clase de implementación.
  2. Los métodos estáticos de la interfaz Java son buenos para proporcionar métodos de utilidad, por ejemplo, verificación nula, clasificación de colecciones, etc.
  3. El método estático de la interfaz Java nos ayuda a proporcionar seguridad al no permitir que las clases de implementación los anulen.
  4. No podemos definir el método estático de la interfaz para los métodos de la clase Object, obtendremos el error del comstackdor como “Este método estático no puede ocultar el método de instancia desde Object”. Esto se debe a que no está permitido en Java, ya que Object es la clase base para todas las clases y no podemos tener un método estático de nivel de clase y otro método de instancia con la misma firma.
  5. Podemos usar métodos estáticos de la interfaz de Java para eliminar clases de utilidad como Colecciones y mover todos sus métodos estáticos a la interfaz correspondiente, que sería fácil de encontrar y usar.

Interfaces funcionales de Java

Antes de concluir la publicación, me gustaría ofrecer una breve introducción a las interfaces funcionales. Una interfaz con exactamente un método abstracto se conoce como Interfaz funcional.

Se ha introducido una nueva anotación @FunctionalInterface para marcar una interfaz como Interfaz funcional. @FunctionalInterface anotación @FunctionalInterface es una función para evitar la adición accidental de métodos abstractos en las interfaces funcionales. Es opcional, pero es una buena práctica usarlo.

Las interfaces funcionales son una característica largamente esperada y buscada de Java 8 porque nos permite usar expresiones lambda para instanciarlas. Se agrega un nuevo paquete java.util.function con un montón de interfaces funcionales para proporcionar tipos de destino para expresiones lambda y referencias de métodos. Examinaremos interfaces funcionales y expresiones lambda en las publicaciones futuras.

Ubicación del recurso:

  1. Cambios en la interfaz Java 8: método estático, método predeterminado

Su explicación parece decente, pero ¿puede ser que parecía que la estaba leyendo todo de un libro de texto? : – /

Lo que más me molesta es, ¿qué tan sólido fue tu ejemplo? ¿Te molestaste en incluir casi todas las diferencias entre el resumen y las 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 entrevistas futuras

Muchos desarrolladores juniors cometen el error de pensar en interfaces, clases abstractas y concretas como pequeñas variaciones de la misma cosa, y eligen una de ellas puramente por razones técnicas: ¿Necesito herencia múltiple? ¿Necesito algún lugar para poner métodos comunes? ¿Debo molestarme con algo más que una clase concreta? Esto está mal, y oculto en estas preguntas está el problema principal: “yo” . Cuando escribe código para usted mismo, rara vez piensa en otros desarrolladores presentes o futuros que trabajen en o con su código.

Las interfaces y las clases abstractas, aunque aparentemente similares desde un punto de vista técnico, tienen significados y propósitos completamente diferentes.

Resumen

  1. Una interfaz define un contrato que alguna implementación cumplirá para usted .

  2. Una clase abstracta proporciona un comportamiento predeterminado que su implementación puede reutilizar.

Estos dos puntos arriba es lo que estoy buscando cuando entrevisto, y es un resumen lo suficientemente compacto. Sigue leyendo para más detalles.

Resumen alternativo

  1. Una interfaz es para definir API públicas
  2. Una clase abstracta es para uso interno y para definir SPI

Por ejemplo

Para decirlo de otra manera: una clase concreta hace el trabajo real, de una manera muy específica. Por ejemplo, un ArrayList utiliza un área contigua de memoria para almacenar una lista de objetos de una manera compacta que ofrece un acceso aleatorio rápido, iteración y cambios en el lugar, pero es terrible en las inserciones, eliminaciones e incluso ocasionalmente adiciones; Mientras tanto, LinkedList utiliza nodos con enlaces dobles para almacenar una lista de objetos, que en cambio ofrece una iteración rápida, cambios en el lugar e inserción / eliminación / adición, pero es terrible en el acceso aleatorio. Estos dos tipos de listas están optimizados para diferentes casos de uso, y es muy importante cómo los va a utilizar. Cuando intentas exprimir el rendimiento de una lista con la que estás interactuando intensamente, y cuando escoges el tipo de lista depende de ti, debes elegir cuidadosamente cuál estás creando.

Por otro lado, a los usuarios de alto nivel de una lista realmente no les importa cómo se implementa realmente, y deben estar aislados de estos detalles. Imaginemos que Java no expone la interfaz de la List , sino que solo tiene una clase de List concreta que es en realidad lo que LinkedList es en este momento. Todos los desarrolladores de Java habrían adaptado su código para ajustarse a los detalles de implementación: evitar el acceso aleatorio, agregar un caché para acelerar el acceso o simplemente volver a implementar ArrayList por su cuenta, aunque sería incompatible con el otro código que realmente funciona solo con List . Eso sería terrible … Pero ahora imagine que los maestros de Java realmente se dan cuenta de que una lista vinculada es terrible para la mayoría de los casos de uso reales, y decidieron cambiar a una lista de arreglos para su única clase List disponible. Esto afectaría el rendimiento de cada progtwig Java en el mundo, y la gente no estaría feliz con eso. Y el principal culpable es que los detalles de implementación estaban disponibles, y los desarrolladores asumieron que esos detalles son un contrato permanente en el que pueden confiar. Es por eso que es importante ocultar los detalles de implementación y solo definir un contrato abstracto. Este es el propósito de una interfaz: definir qué clase de entrada acepta un método y qué tipo de salida se espera, sin exponer todas las agallas que tentarían a los progtwigdores a modificar su código para que se ajuste a los detalles internos que podrían cambiar con cualquier actualización futura .

Una clase abstracta está en el medio entre interfaces y clases concretas. Se supone que ayuda a las implementaciones a compartir código común o aburrido. Por ejemplo, AbstractCollection proporciona implementaciones básicas para isEmpty basado en el tamaño es 0, contains como iterar y comparar, addAll como add , y así sucesivamente. Esto permite que las implementaciones se centren en las partes cruciales que las diferencian: cómo almacenar y recuperar datos.

Otra perspectiva: API versus SPI

Las interfaces son pasarelas de baja cohesión entre diferentes partes del código. Permiten que las bibliotecas existan y evolucionen sin romper a todos los usuarios de la biblioteca cuando algo cambia internamente. Se llama Interfaz de progtwigción de aplicaciones , no Clases de progtwigción de aplicaciones. En una escala menor, también permiten que múltiples desarrolladores colaboren exitosamente en proyectos a gran escala, al separar diferentes módulos a través de interfaces bien documentadas.

Las clases abstractas son ayudantes de alta cohesión para usar cuando se implementa una interfaz, asumiendo algún nivel de detalles de implementación. Alternativamente, las clases abstractas se usan para definir SPI, Interfaces de proveedor de servicio.

La diferencia entre una API y una SPI es sutil, pero importante: para una API, la atención se centra en quién la usa y, para una SPI, se centra en quién la implementa .

Agregar métodos a una API es fácil, todos los usuarios existentes de la API seguirán comstackndo. Agregar métodos a un SPI es difícil, ya que cada proveedor de servicios (implementación concreta) tendrá que implementar los nuevos métodos. Si las interfaces se utilizan para definir un SPI, un proveedor tendrá que lanzar una nueva versión cada vez que cambie el contrato de SPI. Si se utilizan clases abstractas en su lugar, los nuevos métodos podrían definirse en términos de métodos abstractos existentes o como accesos de throw not implemented exception , que al menos permitirán que una versión anterior de la implementación de un servicio se compile y ejecute.

Una nota sobre Java 8 y métodos predeterminados

Aunque Java 8 introdujo métodos predeterminados para las interfaces, lo que hace que la línea entre las interfaces y las clases abstractas sea aún más borrosa, no fue así para que las implementaciones puedan reutilizar el código, sino para facilitar el cambio de interfaces que sirven como API y como SPI (o se usan incorrectamente para definir SPI en lugar de clases abstractas).

“Conocimiento del libro”

Los detalles técnicos proporcionados en la respuesta del OP se consideran “conocimiento del libro” porque suele ser el enfoque utilizado en la escuela y en la mayoría de los libros de tecnología sobre un idioma: qué es una cosa, no cómo usarla en la práctica, especialmente en aplicaciones a gran escala .

Aquí hay una analogía: supuse que la pregunta era:

¿Qué es mejor alquilar para una noche de graduación, un automóvil o una habitación de hotel?

La respuesta técnica suena como:

Bueno, en un automóvil puedes hacerlo más rápido, pero en una habitación de hotel puedes hacerlo más cómodamente. Por otro lado, la habitación del hotel está en un solo lugar, mientras que en el automóvil puedes hacerlo en más lugares, como, digamos que puedes ir al punto de vista para disfrutar de una hermosa vista, o en un autocine, o muchos otros lugares, o incluso en más de un lugar. Además, la habitación del hotel tiene una ducha.

Eso es todo cierto, pero se pierde por completo el hecho de que son dos cosas completamente diferentes, y ambas se pueden usar al mismo tiempo para diferentes propósitos, y el aspecto “hacerlo” no es lo más importante de ninguna de las dos opciones . The answer lacks perspective, it shows an immature way of thinking, while correctly presenting true “facts”.

An interface is a “contract” where the class that implements the contract promises to implement the methods. An example where I had to write an interface instead of a class was when I was upgrading a game from 2D to 3D. I had to create an interface to share classes between the 2D and the 3D version of the game.

 package adventure; import java.awt.*; public interface Playable { public void playSound(String s); public Image loadPicture(String s); } 

Then I can implement the methods based on the environment, while still being able to call those methods from an object that doesn’t know which version of the game that is loading.

public class Adventure extends JFrame implements Playable

public class Dungeon3D extends SimpleApplication implements Playable

public class Main extends SimpleApplication implements AnimEventListener, ActionListener, Playable

Typically, in the gameworld, the world can be an abstract class that performs methods on the game:

 public abstract class World... public Playable owner; public Playable getOwner() { return owner; } public void setOwner(Playable owner) { this.owner = owner; } 

Abstract classes are meant to be inherited from, and when one class inherits from another it means that there is a strong relationship between the 2 classes. With an interface on the other hand, the relationship between the interface itself and the class implementing the interface is not necessarily strong. So, we can summarize this first point by saying that an abstract class would be more appropriate when there is a strong relationship between the abstract class and the classes that will derive from it. Again, this is because an abstract class is very closely linked to inheritance, which implies a strong relationship. But, with interfaces there need not be a strong relationship between the interface and the classes that implement the interface. Java interface can extend multiple interface also Java class can implement multiple interfaces, Which means interface can provide more polymorphism support than abstract class . By extending abstract class, a class can only participate in one Type hierarchy but by using interface it can be part of multiple type hierarchies.

In order to implement interface in Java, until your class is abstract, you need to provide implementation of all methods, which is very painful. On the other hand abstract class may help you in this case by providing default implementation.

What about thinking the following way:

  • A relationship between a class and an abstract class is of type “is-a”
  • A relationship between a class and an interface is of type “has-a”

So when you have an abstract class Mammals, a subclass Human, and an interface Driving, then you can say

  • each Human is-a Mammal
  • each Human has-a Driving (behavior)

My suggestion is that the book knowledge phrase indicates that he wanted to hear the semantic difference between both (like others here already suggested).

Abstract classes are not pure abstraction bcz its collection of concrete(implemented methods) as well as unimplemented methods. But Interfaces are pure abstraction bcz there are only unimplemented methods not concrete methods.

Why Abstract classes?

  1. If user want write common functionality for all objects.
  2. Abstract classes are best choice for reimplementation in future that to add more functionality without affecting of end user.

Why Interfaces?

  1. If user want to write different functionality that would be different functionality on objects.
  2. Interfaces are best choice that if not need to modify the requirements once interface has been published.

The main difference what i have observed was that abstract class provides us with some common behaviour implemented already and subclasses only needs to implement specific functionality corresponding to them. where as for an interface will only specify what tasks needs to be done and no implementations will be given by interface. I can say it specifies the contract between itself and implemented classes.

An interface is like a set of genes that are publicly documented to have some kind of effect: A DNA test will tell me whether I’ve got them – and if I do, I can publicly make it known that I’m a “carrier” and part of my behavior or state will conform to them. (But of course, I may have many other genes that provide traits outside this scope.)

An abstract class is like the dead ancestor of a single-sex species (*): She can’t be brought to life but a living (ie non-abstract ) descendant inherits all her genes.

(*) To stretch this metaphor, let’s say all members of the species live to the same age. This means all ancestors of a dead ancestor must also be dead – and likewise, all descendants of a living ancestor must be alive.

I do interviews for work and i would look unfavourably on your answer aswell (sorry but im very honest). It does sound like you’ve read about the difference and revised an answer but perhaps you have never used it in practice.

A good explanation as to why you would use each can be far better than having a precise explanation of the difference. Employers ultimatley want programers to do things not know them which can be hard to demonstrate in an interview. The answer you gave would be good if applying for a technical or documentation based job but not a developers role.

Best of luck with interviews in the future.

Also my answer to this question is more about interview technique rather than the technical material youve provided. Perhaps consider reading about it. https://workplace.stackexchange.com/ can be an excellent place for this sort of thing.

An interface is purely abstract. we dont have any implementation code in interface.

Abstract class contains both methods and its implementation.

click here to watch tutorial on interfaces and abstract classes

The main difference what i have observed was that abstract class provides us with some common behaviour implemented already and subclasses only needs to implement specific functionality corresponding to them. where as for an interface will only specify what tasks needs to be done and no implementations will be given by interface. I can say it specifies the contract between itself and implemented classes.

You choose Interface in Java to avoid the Diamond Problem in multiple inheritance .

If you want all of your methods to be implemented by your client you go for interface. It means you design the entire application at abstract.

You choose abstract class if you already know what is in common. For example Take an abstract class Car . At higher level you implement the common car methods like calculateRPM() . It is a common method and you let the client implement his own behavior like
calculateMaxSpeed() etc. Probably you would have explained by giving few real time examples which you have encountered in your day to day job.

Even I have faced the same question in multiple interviews and believe me it makes your time miserable to convince the interviewer. If I inherent all the answers from above then I need to add one more key point to make it more convincing and utilizing OO at its best

In case you are not planning any modification in the rules , for the subclass to be followed, for a long future, go for the interface, as you wont be able to modify in it and if you do so, you need to go for the changes in all the other sub classes, whereas, if you think, you want to reuse the functionality, set some rules and also make it open for modification , go for Abstract class.

Think in this way, you had used a consumble service or you had provided some code to world and You have a chance to modify something, suppose a security check And If I am being a consumer of the code and One morning after a update , I find all read marks in my Eclipse, entire application is down. So to prevent such nightmares, use Abstract over Interfaces

I think this might convince the Interviewer to a extent…Happy Interviews Ahead.

From what I understand, an Interface, which is comprised of final variables and methods with no implementations, is implemented by a class to obtain a group of methods or methods that are related to each other. On the other hand, an abstract class, which can contain non-final variables and methods with implementations, is usually used as a guide or as a superclass from which all related or similar classes inherits from. In other words, an abstract class contains all the methods/variables that are shared by all its subclasses.

In abstract class, you can write default implementation of methods! But in Interface you can not. Basically, In interface there exist pure virtual methods which have to be implemented by the class which implements the interface.

hmm now the people are hungery practical approach, you are quite right but most of interviewer looks as per their current requirment and want a practical approach.

after finishing your answer you should jump on the example:

Abstracto:

for example we have salary function which have some parametar common to all employee. then we can have a abstract class called CTC with partialy defined method body and it will got extends by all type of employee and get redeined as per their extra beefits. For common functonality.

 public abstract class CTC { public int salary(int hra, int da, int extra) { int total; total = hra+da+extra; //incentive for specific performing employee //total = hra+da+extra+incentive; return total; } } class Manger extends CTC { } class CEO extends CTC { } class Developer extends CTC { } 

Interfaz

interface in java allow to have interfcae functionality without extending that one and you have to be clear with the implementation of signature of functionality that you want to introduce in your application. it will force you to have definiton. For different functionality. public interface EmployeType {

  public String typeOfEmployee(); } class ContarctOne implements EmployeType { @Override public String typeOfEmployee() { return "contract"; } } class PermanentOne implements EmployeType { @Override public String typeOfEmployee() { return "permanent"; } } 

you can have such forced activity with abstract class too by defined methgos as a abstract one, now a class tha extends abstract class remin abstract one untill it override that abstract function.

When I am trying to share behavior between 2 closely related classes, I create an abstract class that holds the common behavior and serves as a parent to both classes.

When I am trying to define a Type, a list of methods that a user of my object can reliably call upon, then I create an interface.

For example, I would never create an abstract class with 1 concrete subclass because abstract classes are about sharing behavior. But I might very well create an interface with only one implementation. The user of my code won’t know that there is only one implementation. Indeed, in a future release there may be several implementations, all of which are subclasses of some new abstract class that didn’t even exist when I created the interface.

That might have seemed a bit too bookish too (though I have never seen it put that way anywhere that I recall). If the interviewer (or the OP) really wanted more of my personal experience on that, I would have been ready with anecdotes of an interface has evolved out of necessity and visa versa.

Una cosa más. Java 8 now allows you to put default code into an interface, further blurring the line between interfaces and abstract classes. But from what I have seen, that feature is overused even by the makers of the Java core libraries. That feature was added, and rightly so, to make it possible to extend an interface without creating binary incompatibility. But if you are making a brand new Type by defining an interface, then the interface should be JUST an interface. If you want to also provide common code, then by all means make a helper class (abstract or concrete). Don’t be cluttering your interface from the start with functionality that you may want to change.

I will try to answer using practical scenario to show the distinction between the two.

Interfaces come with zero payload ie no state has to be maintained and thus are better choice to just associate a contract (capability) with a class.

For example, say I have a Task class that performs some action, now to execute a task in separate thread I don’t really need to extend Thread class rather better choice is to make Task implement Runnable interface (ie implement its run() method) and then pass object of this Task class to a Thread instance and call its start() method.

Now you can ask what if Runnable was a abstract class?

Well technically that was possible but design wise that would have been a poor choice reason being:

  • Runnable has no state associated with it and neither it ‘offers’ any default implementation for the run() method
  • Task would have to extend it thus it couldn’t extend any other class
  • Task has nothing to offer as specialization to Runnable class, all it needs is to override run() method

In other words, Task class needed a capability to be run in a thread which it achieved by implementing Runnable interface verses extending the Thread class that would make it a thread.

Simply put us interface to define a capability (contract), while use a abstract class to define skeleton (common/partial) implementation of it.

Disclaimer: silly example follows, try not to judge 😛

 interface Forgiver { void forgive(); } abstract class GodLike implements Forgiver { abstract void forget(); final void forgive() { forget(); } } 

Now you have been given a choice to be GodLike but you may choose to be Forgiver only (ie not GodLike) and do:

 class HumanLike implements Forgiver { void forgive() { // forgive but remember } } 

Or you may may choose to be GodLike and do:

 class AngelLike extends GodLike { void forget() { // forget to forgive } } 

PS with java 8 interface can also have static as well default (overridable implementation) methods and thus difference b/w interface and abstract class is even more narrowed down.

Almost everything seems to be covered here already.. Adding just one more point on practical implementation of abstract class:

abstract keyword is also used just prevent a class from being instantiated. If you have a concrete class which you do not want to be instantiated – Make it abstract .

Your answer is ok, but I think he was looking for this kind of answer:

Abstract class

  • La clase abstracta puede tener métodos abstractos y no abstractos.
  • La clase abstracta no admite herencia múltiple.
  • Abstract class can have final, non-final, static and non-static variables.
  • La clase abstracta puede proporcionar la implementación de la interfaz.

Interfaz

  • Interface can have default, static and abstract methods.
  • La interfaz admite herencia múltiple.
  • Interface has only static and final variables.
  • Interface can’t provide the implementation of abstract class.

From what I understand and how I approach,

Interface is like a specification/contract, any class that implements a interface class have to implement all the methods defined in the abstract class (except default methods (introduced in java 8))

Whereas I define a class abstract when I know the implementation required for some methods of the class and some methods I still do not know what will be the implementation(we might know the function signature but not the implementation). I do this so that later in the part of development when i know how these methods are to be implemented, i can just extend this abstract class and implement these methods.

Note: You cannot have function body in interface methods unless the method is static or default.

Yes, your responses were technically correct but where you went wrong was not showing them you understand the upsides and downsides of choosing one over the other. Additionally, they were probably concerned/freaked out about compatibility of their codebase with upgrades in the future. This type of response may have helped (in addition to what you said):

“Choosing an Abstract Class over an Interface Class depends on what we project the future of the code will be.

Abstract classes allow better forward-compatibility because you can continue adding behavior to an Abstract Class well into the future without breaking your existing code –> this is not possible with an Interface Class.

On the other hand, Interface Classes are more flexible than Abstract Classes. This is because they can implement multiple interfaces . The thing is Java does not have multiple inheritances so using abstract classes won’t let you use any other class hierarchy structure…

So, in the end a good general rule of thumb is: Prefer using Interface Classes when there are no existing/default implementations in your codebase. And, use Abstract Classes to preserve compatibility if you know you will be updating your class in the future.”

Good luck on your next interview!

I believe what the interviewer was trying to get at was probably the difference between interface and implementation.

The interface – not a Java interface, but “interface” in more general terms – to a code module is, basically, the contract made with client code that uses the interface.

The implementation of a code module is the internal code that makes the module work. Often you can implement a particular interface in more than one different way, and even change the implementation without client code even being aware of the change.

A Java interface should only be used as an interface in the above generic sense, to define how the class behaves for the benefit of client code using the class, without specifying any implementation. Thus, an interface includes method signatures – the names, return types, and argument lists – for methods expected to be called by client code, and in principle should have plenty of Javadoc for each method describing what that method does. The most compelling reason for using an interface is if you plan to have multiple different implementations of the interface, perhaps selecting an implementation depending on deployment configuration.

A Java abstract class, in contrast, provides a partial implementation of the class, rather than having a primary purpose of specifying an interface. It should be used when multiple classes share code, but when the subclasses are also expected to provide part of the implementation. This permits the shared code to appear in only one place – the abstract class – while making it clear that parts of the implementation are not present in the abstract class and are expected to be provided by subclasses.

your answer is right but the interviewer needs you to differentiate according to software engineering perspective not according to the details of Java.

Palabras simples:

An Interface is like the interface of a shop anything that is shown on it should be there in the shop, so any method in the Interface must be there implemented in the concrete class. Now what if some classes share some exact methods and varies in others. Suppose the Interface is about a shop that contains two things and suppose we have two shops both contain sport equipment but one has clothes extra and the other has shoes extra. So what you do is making an abstract class for Sport that implements the Sports method and leave the other method unimplemented. Abstract class here means that this shop doesn’t exist itself but it is the base for other classes/shops. This way you are organising the code, avoiding errors of replicating the code, unifying the code, and ensuring re-usability by some other class.