Come dovrei aver spiegato la differenza tra un’interfaccia e una class astratta?

In una delle mie interviste, mi è stato chiesto di spiegare la differenza tra un’interfaccia e una class astratta .

Ecco la mia risposta:

I metodi di un’interfaccia Java sono implicitamente astratti e non possono avere implementazioni. Una class astratta Java può avere metodi di istanza che implementano un comportamento predefinito.

Le variabili dichiarate in un’interfaccia Java sono per default definitive. Una class astratta può contenere variabili non finali.

I membri di un’interfaccia Java sono pubblici per impostazione predefinita. Una class astratta Java può avere i soliti sapori dei membri della class come privati, protetti, ecc.

Un’interfaccia Java dovrebbe essere implementata usando la parola chiave “implements”; Una class astratta Java dovrebbe essere estesa usando la parola chiave “extends”.

Un’interfaccia può estendere solo un’altra interfaccia Java, una class astratta può estendere un’altra class Java e implementare più interfacce Java.

Una class Java può implementare più interfacce ma può estendere solo una class astratta.

Tuttavia, l’intervistatore non era soddisfatto e mi ha detto che questa descrizione rappresentava ” conoscenza libresca “.

Mi ha chiesto una risposta più pratica, spiegando quando avrei scelto una class astratta su un’interfaccia, usando esempi pratici .

Dove ho sbagliato?

Ti darò un esempio prima:

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

Supponiamo ora di avere 3 database nella tua applicazione. Quindi ogni implementazione per quel database deve definire i due metodi sopra elencati:

 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 } 

Ma cosa succede se encryptPassword () non dipende dal database, ed è lo stesso per ogni class? Quindi quanto sopra non sarebbe un buon approccio.

Invece, considera questo approccio:

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

Ora in ogni class figlia, abbiamo solo bisogno di implementare un metodo – il metodo che dipende dal database.

Ho fatto del mio meglio e spero che questo chiarisca i tuoi dubbi.

Niente è perfetto in questo mondo. Potrebbero aver aspettato più di un approccio pratico.

Ma dopo la tua spiegazione potresti aggiungere queste righe con un approccio leggermente diverso.

  1. Le interfacce sono regole (regole perché devi dare loro un’implementazione che non puoi ignorare o evitare, in modo che vengano imposte come regole) che funzioni come un documento di intesa comune tra i vari team nello sviluppo del software.

  2. Le interfacce danno l’idea di ciò che deve essere fatto, ma non di come sarà fatto. Quindi l’implementazione dipende completamente dallo sviluppatore seguendo le regole date (significa data firma dei metodi).

  3. Le classi astratte possono contenere dichiarazioni astratte, implementazioni concrete o entrambe.

  4. Le dichiarazioni astratte sono come regole da seguire e le implementazioni concrete sono come le linee guida (puoi usarla così com’è o puoi ignorarla sopraffacendo e dando la tua implementazione ad essa).

  5. Inoltre, i metodi con la stessa firma possono cambiare il comportamento in un contesto differente sono forniti come dichiarazioni di interfaccia come regole da implementare di conseguenza in diversi contesti.

Modifica: Java 8 facilita la definizione di metodi predefiniti e statici nell’interfaccia.

 public interface SomeInterfaceOne { void usualAbstractMethod(String inputString); default void defaultMethod(String inputString){ System.out.println("Inside SomeInterfaceOne defaultMethod::"+inputString); } } 

Ora, quando una class implementerà SomeInterface, non è obbligatorio fornire l’implementazione per i metodi di interfaccia predefiniti.

Se abbiamo un’altra interfaccia con i seguenti metodi:

 public interface SomeInterfaceTwo { void usualAbstractMethod(String inputString); default void defaultMethod(String inputString){ System.out.println("Inside SomeInterfaceTwo defaultMethod::"+inputString); } } 

Java non consente l’estensione di più classi perché genera il “Problema Diamond” in cui il compilatore non è in grado di decidere quale metodo della superclass utilizzare. Con i metodi predefiniti, il problema del diamante si presenterà anche per le interfacce. Perché se una class sta implementando entrambi

 SomeInterfaceOne and SomeInterfaceTwo 

e non implementa il metodo di default comune, il compilatore non può decidere quale scegliere. Per evitare questo problema, in java 8 è obbligatorio implementare metodi di default comuni di diverse interfacce. Se una class implementa entrambe le interfacce di cui sopra, deve fornire l’implementazione per il metodo defaultMethod () altrimenti il ​​compilatore genererà un errore in fase di compilazione.

Hai fatto un buon riassunto delle differenze pratiche di utilizzo e implementazione, ma non hai detto nulla sulla differenza di significato.

Un’interfaccia è una descrizione del comportamento che avrà una class di implementazione. La class di implementazione garantisce che avrà questi metodi che possono essere utilizzati su di esso. È fondamentalmente un contratto o una promise che la class deve fare.

Una class astratta è una base per diverse sottoclassi che condividono comportamenti che non devono essere creati ripetutamente. Le sottoclassi devono completare il comportamento e avere la possibilità di sovrascrivere il comportamento predefinito (purché non sia definito final o private ).

Troverai buoni esempi nel pacchetto java.util che include interfacce come List e classi astratte come AbstractList che implementa già l’interfaccia. La documentazione ufficiale descrive AbstractList come segue:

Questa class fornisce un’implementazione scheletrica dell’interfaccia List per ridurre al minimo lo sforzo richiesto per implementare questa interfaccia supportata da un archivio dati “accesso casuale” (come un array).

Un’interfaccia è costituita da variabili singleton (finale statico pubblico) e metodi astratti pubblici. Normalmente preferiamo usare un’interfaccia in tempo reale quando sappiamo cosa fare ma non sappiamo come farlo .

Questo concetto può essere meglio compreso con l’esempio:

Considera una class di pagamento Il pagamento può essere effettuato in molti modi, come PayPal, carta di credito, ecc. Di solito, prendiamo Pagamento come nostra interfaccia che contiene un metodo makePayment() e CreditCard e PayPal sono le due classi di implementazione.

 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... } } 

Nell’esempio sopra CreditCard e PayPal sono due classi / strategie di implementazione. Un’interfaccia ci consente anche il concetto di ereditarietà multipla in Java che non può essere realizzato da una class astratta.

Scegliamo una class astratta quando ci sono alcune funzionalità per le quali sappiamo cosa fare e altre funzionalità che sappiamo come eseguire .

Considera il seguente esempio:

 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. } } 

Se in futuro aggiungiamo metodi (concreti / astratti) a una determinata class astratta, la class di implementazione non avrà bisogno di modificarne il codice. Tuttavia, se aggiungiamo metodi in un’interfaccia in futuro, dobbiamo aggiungere implementazioni a tutte le classi che hanno implementato tale interfaccia, altrimenti si verificano errori di compilazione del tempo.

Ci sono altre differenze, ma queste sono le principali che potrebbero essere state le aspettative del vostro intervistatore. Spero che questo sia stato utile.

Tutte le tue dichiarazioni sono valide tranne la tua prima affermazione (dopo la versione Java 8):

I metodi di un’interfaccia Java sono implicitamente astratti e non possono avere implementazioni

Dalla pagina della documentazione:

Un’interfaccia è un tipo di riferimento, simile a una class, che può contenere solo costanti, firme del metodo, metodi predefiniti, metodi statici e tipi nidificati

I corpi dei metodi esistono solo per metodi predefiniti e metodi statici.

Metodi predefiniti:

Un’interfaccia può avere metodi predefiniti , ma sono diversi dai metodi astratti in classi astratte.

I metodi predefiniti consentono di aggiungere nuove funzionalità alle interfacce delle librerie e garantire la compatibilità binaria con il codice scritto per le versioni precedenti di tali interfacce.

Quando estendi un’interfaccia che contiene un metodo predefinito, puoi fare quanto segue:

  1. Non menzionare affatto il metodo predefinito, che consente all’interfaccia estesa di ereditare il metodo predefinito.
  2. Redeclare il metodo predefinito, che lo rende abstract .
  3. Ridefinire il metodo predefinito, che lo sovrascrive.

Metodi statici:

Oltre ai metodi predefiniti, è ansible definire metodi statici nelle interfacce. (Un metodo statico è un metodo associato alla class in cui è definito piuttosto che a qualsiasi object. Ogni istanza della class condivide i suoi metodi statici.)

Ciò semplifica l’organizzazione dei metodi di supporto nelle tue librerie;

Esempio di codice dalla pagina di documentazione interface con metodi static e 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)); } } 

Usa le seguenti linee guida per scegliere se usare un’interfaccia o una class astratta.

Interfaccia:

  1. Per definire un contratto (preferibilmente senza stato – voglio dire nessuna variabile)
  2. Per colbind classi non correlate con ha una capacità.
  3. Per dichiarare variabili costanti pubbliche ( stato immutabile )

Classe astratta:

  1. Condividi codice tra diverse classi strettamente correlate. Stabilisce è una relazione.

  2. Condividi lo stato comune tra classi correlate (lo stato può essere modificato in classi concrete)

Articoli correlati:

Interface vs Abstract Class (OO generale)

Implementa vs estende: quando usare? Qual è la differenza?

Passando attraverso questi esempi, puoi capirlo

Le classi non correlate possono avere capacità attraverso l’interfaccia, ma le classi correlate cambiano il comportamento attraverso l’estensione delle classi di base.

Differenza tra class Abstact e interfaccia

  1. Classi astratte contro interfacce in Java 8
  2. Differenza concettuale:

Interfaccia metodi predefiniti in Java 8

  1. Qual è il metodo predefinito?
  2. Errore di compilazione del metodo ForEach risolto utilizzando il metodo predefinito
  3. Metodo predefinito e problemi di ambiguità con ereditarietà multipla
  4. Punti importanti sui metodi di default dell’interfaccia java:

Metodo statico di interfaccia Java

  1. Metodo di interfaccia Java, esempio di codice, metodo statico e metodo predefinito
  2. Punti importanti sul metodo statico dell’interfaccia java:

Interfacce funzionali Java



Classi astratte contro interfacce in Java 8

Le modifiche all’interfaccia di Java 8 includono metodi statici e metodi predefiniti nelle interfacce. Prima di Java 8, potevamo avere solo dichiarazioni di metodo nelle interfacce. Ma da Java 8, possiamo avere metodi predefiniti e metodi statici nelle interfacce.

Dopo aver introdotto il metodo predefinito, sembra che le interfacce e le classi astratte siano uguali. Tuttavia, sono ancora diversi concetti in Java 8.

La class astratta può definire il costruttore. Sono più strutturati e possono avere uno stato associato a loro. Mentre al contrario, il metodo predefinito può essere implementato solo nei termini di invocare altri metodi di interfaccia, senza riferimento a uno stato particolare dell’implementazione. Quindi, entrambi utilizzano per scopi diversi e la scelta tra due dipende molto dal contesto dello scenario.

Differenza concettuale:

Le classi astratte sono valide per implementazioni scheletriche (cioè parziali) di interfacce ma non dovrebbero esistere senza un’interfaccia di corrispondenza.

Quindi, quando le classi astratte vengono effettivamente ridotte ad essere a bassa visibilità, implementazioni scheletriche di interfacce, i metodi predefiniti possono anche portarlo via? Decisamente: No! L’implementazione di interfacce richiede quasi sempre alcuni o tutti quegli strumenti per la creazione di classi che mancano di metodi predefiniti. E se qualche interfaccia non lo fa, è chiaramente un caso speciale, che non dovrebbe portarti fuori strada.

Interfaccia metodi predefiniti in Java 8

Java 8 introduce la nuova funzione ” Metodo predefinito ” o (metodi Defender), che consente allo sviluppatore di aggiungere nuovi metodi alle interfacce senza interrompere l’implementazione esistente di queste interfacce. Fornisce flessibilità per consentire all’interfaccia di definire l’implementazione che verrà utilizzata come impostazione predefinita nella situazione in cui una class concreta non riesce a fornire un’implementazione per tale metodo.

Considera un piccolo esempio per capire come funziona:

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

La seguente class verrà compilata correttamente in Java JDK 8,

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

Se si crea un’istanza di OldInterfaceImpl:

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

Metodo predefinito:

I metodi predefiniti non sono mai definitivi, non possono essere sincronizzati e non possono sovrascrivere i metodi di Object. Sono sempre pubblici, il che limita fortemente la capacità di scrivere metodi brevi e riutilizzabili.

I metodi predefiniti possono essere forniti a un’interfaccia senza influire sulle classi di implementazione in quanto include un’implementazione. Se ogni metodo aggiunto in un’interfaccia definita con l’implementazione, non è interessata alcuna class di implementazione. Una class di implementazione può sovrascrivere l’implementazione predefinita fornita dall’interfaccia.

I metodi predefiniti consentono di aggiungere nuove funzionalità alle interfacce esistenti senza interrompere l’implementazione precedente di queste interfacce.

Quando estendiamo un’interfaccia che contiene un metodo predefinito, possiamo eseguire il seguente,

  1. Non sovrascrive il metodo predefinito e erediterà il metodo predefinito.
  2. Sostituisci il metodo predefinito in modo simile ad altri metodi che sovrascriviamo nella sottoclass.
  3. Redeclare il metodo predefinito come abstract, che forza la sottoclass a sovrascriverlo.

Errore di compilazione del metodo ForEach risolto utilizzando il metodo predefinito

Per Java 8, le raccolte JDK sono state estese e per ogni metodo viene aggiunto all’intera raccolta (che funziona in congiunzione con lambdas). Con il modo convenzionale, il codice appare come di seguito,

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

Di conseguenza, ogni class di implementazione con errori di compilazione, quindi, aggiunge un metodo predefinito con un’implementazione richiesta in modo che l’implementazione esistente non debba essere modificata.

L’interfaccia Iterable con il metodo Default è sotto,

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

Lo stesso meccanismo è stato utilizzato per aggiungere Stream in JDK Interface senza rompere le Classi di implementazione.


Metodo predefinito e problemi di ambiguità con ereditarietà multipla

Poiché java Class può implementare più interfacce e ogni interfaccia può definire il metodo predefinito con la stessa firma del metodo, i metodi ereditati possono quindi entrare in conflitto l’uno con l’altro.

Considera l’esempio seguente,

 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 { } 

Il codice sopra non riuscirà a compilare con il seguente errore,

java: class Impl eredita i default non collegati per defaultMethod () dai tipi InterfaceA e InterfaceB

Per correggere questa class, è necessario fornire l’implementazione del metodo predefinito:

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

Inoltre, se vogliamo invocare l’implementazione predefinita fornita da qualsiasi super interfaccia piuttosto che la nostra implementazione, possiamo procedere come segue,

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

Possiamo scegliere qualsiasi implementazione predefinita o entrambi come parte del nostro nuovo metodo.

Punti importanti sui metodi di default dell’interfaccia java:

  1. I metodi di default dell’interfaccia Java ci aiuteranno ad estendere le interfacce senza il timore di rompere le classi di implementazione.
  2. I metodi di default dell’interfaccia Java hanno messo a ponte le differenze tra le interfacce e le classi astratte.
  3. I metodi di default dell’interfaccia di Java 8 ci aiuteranno ad evitare classi di utilità, come il metodo della class Collections che può essere fornito nelle interfacce stesse.
  4. I metodi di default dell’interfaccia Java ci aiuteranno a rimuovere le classi di implementazione di base, possiamo fornire l’implementazione predefinita e le classi di implementazione possono scegliere quale sovrascrivere.
  5. Uno dei motivi principali per l’introduzione dei metodi predefiniti nelle interfacce è il potenziamento dell’API Collections in Java 8 per supportare espressioni lambda.
  6. Se una class nella gerarchia ha un metodo con la stessa firma, i metodi predefiniti diventano irrilevanti. Un metodo predefinito non può sovrascrivere un metodo da java.lang.Object. Il ragionamento è molto semplice, perché Object è la class base per tutte le classi java. Quindi, anche se i metodi della class Object sono definiti come metodi predefiniti nelle interfacce, sarà inutile perché verrà sempre utilizzato il metodo della class Object. Ecco perché per evitare confusione, non possiamo avere metodi predefiniti che stanno sovrascrivendo i metodi della class Object.
  7. I metodi predefiniti dell’interfaccia Java vengono anche definiti metodi Defender o metodi di estensione virtuale.

Link alle risorse:

  1. Interfaccia con i metodi predefiniti rispetto alla class Abstract in Java 8
  2. Classe astratta contro interfaccia nell’era JDK 8
  3. Evoluzione dell’interfaccia tramite metodi di estensione virtuale

Metodo statico di interfaccia Java

Metodo di interfaccia Java, esempio di codice, metodo statico e metodo predefinito

Il metodo statico dell’interfaccia Java è simile al metodo predefinito, tranne per il fatto che non possiamo sovrascriverli nelle classi di implementazione. Questa funzione ci aiuta ad evitare risultati indesiderati in caso di scarsa implementazione nelle classi di implementazione. Diamo un’occhiata a questo con un semplice esempio.

 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; } } 

Ora vediamo una class di implementazione che sta avendo il metodo isNull () con un’implementazione scadente.

 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"); } } 

Notare che isNull (String str) è un metodo di class semplice, non sovrascrive il metodo dell’interfaccia. Ad esempio, se aggiungeremo l’annotazione @Override al metodo isNull (), ciò comporterà l’errore del compilatore.

Ora quando eseguiremo l’applicazione, otterremo l’output seguente.

Interfaccia Null Check

Impl Null Check

Se rendiamo il metodo di interfaccia da statico a predefinito, otterremo l’output seguente.

Impl Null Check

MyData Print ::

Impl Null Check

Il metodo statico dell’interfaccia Java è visibile solo per i metodi di interfaccia, se rimuoviamo il metodo isNull () dalla class MyDataImpl, non saremo in grado di utilizzarlo per l’object MyDataImpl. Tuttavia, come altri metodi statici, possiamo usare i metodi statici dell’interfaccia usando il nome della class. Ad esempio, una dichiarazione valida sarà:

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

Punti importanti sul metodo statico dell’interfaccia java:

  1. Il metodo statico di interfaccia Java è parte dell’interfaccia, non possiamo usarlo per gli oggetti di class di implementazione.
  2. I metodi statici dell’interfaccia Java sono utili per fornire metodi di utilità, ad esempio controllo nullo, ordinamento di raccolta, ecc.
  3. Il metodo statico dell’interfaccia Java ci aiuta a garantire la sicurezza non consentendo alle classi di implementazione di sovrascriverle.
  4. Non possiamo definire il metodo statico di interfaccia per i metodi della class Object, avremo l’errore del compilatore come “Questo metodo statico non può hide il metodo dell’istanza da Object”. Questo perché non è consentito in java, poiché Object è la class base per tutte le classi e non possiamo avere un metodo statico di livello di class e un altro metodo di istanza con la stessa firma.
  5. Possiamo utilizzare i metodi statici dell’interfaccia java per rimuovere classi di utilità come Raccolte e spostare tutti i metodi statici nell’interfaccia corrispondente, che sarebbe facile da trovare e utilizzare.

Interfacce funzionali Java

Prima di concludere il post, vorrei fornire una breve introduzione alle interfacce funzionali. Un’interfaccia con esattamente un metodo astratto è nota come interfaccia funzionale.

Una nuova annotazione @FunctionalInterface è stata introdotta per contrassegnare un’interfaccia come interfaccia funzionale. @FunctionalInterface annotazione @FunctionalInterface è una funzione per evitare l’aggiunta accidentale di metodi astratti nelle interfacce funzionali. È opzionale ma è buona pratica usarlo.

Le interfacce funzionali sono funzionalità tanto attese e ricercate di Java 8 perché ci consentono di utilizzare espressioni lambda per istanziarle. Viene aggiunto un nuovo pacchetto java.util.function con un gruppo di interfacce funzionali per fornire tipi di destinazione per espressioni lambda e riferimenti al metodo. Analizzeremo le interfacce funzionali e le espressioni lambda nei prossimi post.

Posizione della risorsa:

  1. Java 8 Interface Changes: metodo statico, metodo predefinito

La tua spiegazione sembra decente, ma potrebbe sembrare che stavi leggendo tutto da un libro di testo? : – /

Quello che mi preoccupa di più è quanto è stato solido il tuo esempio? Ti sei preso la briga di includere quasi tutte le differenze tra astratto e interfacce?

Personalmente, suggerirei questo link: http://mindprod.com/jgloss/interfacevsabstract.html#TABLE

per un elenco esaustivo delle differenze

Spero che aiuti te e tutti gli altri lettori nelle loro future interviste

Molti sviluppatori junior commettono l’errore di pensare a interfacce, classi astratte e concrete come lievi variazioni della stessa cosa e ne scelgono uno solo per motivi tecnici: ho bisogno di ereditarietà multipla? Ho bisogno di un posto dove mettere i metodi comuni? Devo preoccuparmi di qualcosa di diverso da una class concreta? Questo è sbagliato, e nascosto in queste domande è il problema principale: “I” . Quando scrivi il codice per te stesso, di rado pensi di altri sviluppatori presenti o futuri che lavorano su o con il tuo codice.

Interfacce e classi astratte, sebbene apparentemente simili dal punto di vista tecnico, hanno significati e scopi completamente diversi.

Sommario

  1. Un’interfaccia definisce un contratto che alcune implementazioni soddisferanno per te .

  2. Una class astratta fornisce un comportamento predefinito che la tua implementazione può riutilizzare.

Questi due punti sopra sono ciò che sto cercando durante l’intervista, ed è un riassunto abbastanza compatto. Continua a leggere per maggiori dettagli.

Riassunto alternativo

  1. Un’interfaccia è per la definizione di API pubbliche
  2. Una class astratta è per uso interno e per definire gli SPI

Per esempio

Per dirla in modo diverso: una class concreta fa il lavoro vero, in un modo molto specifico. Ad esempio, un ArrayList utilizza un’area contigua di memoria per memorizzare un elenco di oggetti in un modo compatto che offre accesso casuale rapido, iterazione e modifiche sul posto, ma è terribile in caso di inserimenti, eliminazioni e talvolta anche aggiunte; nel frattempo, una LinkedList usa nodes a doppio collegamento per memorizzare un elenco di oggetti, che invece offre iterazioni veloci, modifiche sul posto e inserimento / cancellazione / aggiunta, ma è terribile all’accesso casuale. Questi due tipi di elenchi sono ottimizzati per diversi casi d’uso, ed è molto importante il modo in cui li userete. Quando stai provando a spremere le prestazioni da un elenco con cui stai interagendo pesantemente, e quando scegli il tipo di elenco dipende da te, dovresti scegliere con attenzione quale istanza stai creando.

D’altro canto, gli utenti di alto livello di un elenco non si preoccupano veramente di come è effettivamente implementato, e dovrebbero essere isolati da questi dettagli. Immaginiamo che Java non abbia esposto l’interfaccia List , ma solo una class List concreta che è in realtà ciò che LinkedList è in questo momento. Tutti gli sviluppatori Java avrebbero adattato il loro codice per adattarsi ai dettagli dell’implementazione: evitare l’accesso casuale, aggiungere una cache per accelerare l’accesso, o semplicemente reimplementare ArrayList da soli, anche se sarebbe incompatibile con tutti gli altri codici che funzionano effettivamente solo con List . Sarebbe terribile … Ma ora immagina che i maestri Java si rendano effettivamente conto che una lista collegata è terribile per la maggior parte dei casi reali di utilizzo e ha deciso di passare a un elenco di array per la loro unica class di List disponibile. Ciò influenzerebbe le prestazioni di ogni programma Java nel mondo e la gente non ne sarebbe felice. Il principale colpevole è che i dettagli dell’implementazione erano disponibili e gli sviluppatori presumevano che quei dettagli fossero un contratto a tempo indeterminato su cui poter fare affidamento. Questo è il motivo per cui è importante hide i dettagli di implementazione e definire solo un contratto astratto. Questo è lo scopo di un’interfaccia: definire quale tipo di input accetta un metodo e quale tipo di output è previsto, senza esporre tutto il coraggio che potrebbe indurre i programmatori a modificare il codice per adattarlo ai dettagli interni che potrebbero cambiare con qualsiasi aggiornamento futuro .

Una class astratta è nel mezzo tra interfacce e classi concrete. Si suppone che aiuti le implementazioni a condividere codice comune o noioso. Ad esempio, AbstractCollection fornisce implementazioni di base per isEmpty base alla dimensione è 0, contains come iterare e confrontare, addAll come add ripetuta e così via. Ciò consente alle implementazioni di concentrarsi sulle parti cruciali che le differenziano: come archiviare e recuperare effettivamente i dati.

Un’altra prospettiva: API contro SPI

Le interfacce sono gateway a bassa coesione tra diverse parti del codice. Consentono alle librerie di esistere ed evolvere senza rompere ogni utente della libreria quando qualcosa cambia internamente. Si chiama Application Programming Interface , non Application Programming Classes. Su scala ridotta, consentono inoltre a più sviluppatori di collaborare con successo su progetti su larga scala, separando diversi moduli attraverso interfacce ben documentate.

Le classi astratte sono helper ad alta coesione da utilizzare quando si implementa un’interfaccia, assumendo alcuni livelli di dettagli di implementazione. In alternativa, le classi astratte vengono utilizzate per definire gli SPI, le interfacce dei provider di servizi.

La differenza tra un’API e una SPI è sottile, ma importante: per un’API, l’attenzione è rivolta a chi la utilizza e, per uno SPI, l’attenzione è rivolta a chi la implementa .

L’aggiunta di metodi a un’API è semplice, tutti gli utenti esistenti dell’API verranno comunque compilati. L’aggiunta di metodi a un SPI è difficile, poiché ogni fornitore di servizi (implementazione concreta) dovrà implementare i nuovi metodi. Se le interfacce vengono utilizzate per definire un SPI, un provider dovrà rilasciare una nuova versione ogni volta che il contratto SPI cambia. Se invece vengono utilizzate classi astratte, è ansible definire nuovi metodi in termini di metodi astratti esistenti o come stub di throw not implemented exception vuoto, che consentiranno almeno una versione precedente di un’implementazione di servizio ancora da compilare ed eseguire.

Una nota su Java 8 e metodi predefiniti

Sebbene Java 8 abbia introdotto i metodi predefiniti per le interfacce, che rende la linea tra interfacce e classi astratte ancora più sfocata, non è stato così che le implementazioni possano riutilizzare il codice, ma per rendere più semplice cambiare le interfacce che fungono sia da API che da SPI (o sono erroneamente usati per definire gli SPI invece delle classi astratte).

“Conoscenza del libro”

I dettagli tecnici forniti nella risposta dell’OP sono considerati “conoscenza del libro” perché questo è solitamente l’approccio utilizzato a scuola e nella maggior parte dei libri di tecnologia su una lingua: che cos’è una cosa, non come usarla nella pratica, specialmente nelle applicazioni su larga scala .

Ecco un’analogia: supposto che la domanda fosse:

Cosa è meglio affittare per la notte del ballo di fine anno, un’auto o una camera d’albergo?

La risposta tecnica suona come:

Bene, in una macchina puoi farlo prima, ma in una stanza d’albergo puoi farlo più comodamente. D’altra parte, la stanza d’albergo si trova in un solo posto, mentre in macchina puoi farlo in più posti, ad esempio, diciamo che puoi andare al punto panoramico per una bella vista, o in un teatro drive-in, o molti altri posti, o anche in più di un posto. Inoltre, la camera d’albergo ha una doccia.

That is all true, but completely misses the points that they are two completely different things, and both can be used at the same time for different purposes, and the “doing it” aspect is not the most important thing about either of the two options. 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 classs 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 classs are meant to be inherited from, and when one class inherits from another it means that there is a strong relationship between the 2 classs. 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 classs 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 classs 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 classs 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 classs?

  1. If user want write common functionality for all objects.
  2. Abstract classs 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 subclasss 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 classs.

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 classs

The main difference what i have observed was that abstract class provides us with some common behaviour implemented already and subclasss 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 classs.

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 classs, 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 consumable 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 classs inherits from. In other words, an abstract class contains all the methods/variables that are shared by all its subclasss.

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:

Abstract:

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 { } 

Interface

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 classs, I create an abstract class that holds the common behavior and serves as a parent to both classs.

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 classs 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 subclasss 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.

One more thing. Java 8 now allows you to put default code into an interface, further blurring the line between interfaces and abstract classs. 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

  • Abstract class can have abstract and non-abstract methods.
  • La class astratta non supporta l’ereditarietà multipla.
  • La class astratta può avere variabili finali, non definitive, statiche e non statiche.
  • La class astratta può fornire l’implementazione dell’interfaccia.

Interface

  • Interface can have default, static and abstract methods.
  • L’interfaccia supporta l’ereditarietà multipla.
  • L’interfaccia ha solo variabili statiche e finali.
  • 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 classs 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 classs 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 classs share code, but when the subclasss 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 subclasss.

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

Parole semplici:

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 classs 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 classs/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.