In una delle mie interviste, mi è stato chiesto di spiegare la differenza tra una Interfaccia e una Classe astratta.
Ecco la mia risposta:
I metodi di un'interfaccia Java sono implicitamente astratti e non possono avere implementazioni. Una classe astratta Java può avere metodi di istanza che implementano un comportamento predefinito.
Le variabili dichiarate in un'interfaccia Java sono per default finali. Una classe astratta può contenere variabili non finali.
I membri di un'interfaccia Java sono pubblici per default. Una classe astratta Java può avere i soliti tipi di membri di classe come private, protetti, ecc.
Un'interfaccia Java dovrebbe essere implementata usando la parola chiave "implements"; Una classe astratta Java dovrebbe essere estesa usando la parola chiave "extends".
Un'interfaccia può estendere solo un'altra interfaccia Java, una classe astratta può estendere un'altra classe Java e implementare più interfacce Java.
Una classe Java può implementare più interfacce ma può estendere solo una classe astratta.
Tuttavia, l'intervistatore non era soddisfatto, e mi ha detto che questa descrizione rappresentava "conoscenza da libro".
Mi ha chiesto una risposta più pratica, spiegandomi quando sceglierei una classe astratta piuttosto che un'interfaccia, usando esempi pratici.
Dove ho sbagliato?
Niente è perfetto in questo mondo. Forse si aspettavano un approccio più pratico.
Ma dopo la tua spiegazione potresti aggiungere queste righe con un approccio leggermente diverso.
Le interfacce sono regole (regole perché si deve dare loro un'implementazione che non si può ignorare o evitare, in modo che siano imposte come regole) che funzionano come un documento di comprensione comune tra vari team nello sviluppo del software.
Le interfacce danno l'idea di cosa deve essere fatto ma non di come sarà fatto. Quindi l'implementazione dipende completamente dallo sviluppatore seguendo le regole date (cioè la firma data dei metodi).
Le classi astratte possono contenere dichiarazioni astratte, implementazioni concrete o entrambe.
Le dichiarazioni astratte sono come regole da seguire e le implementazioni concrete sono come linee guida (puoi usarle così come sono o puoi ignorarle sovrascrivendo e dando la tua implementazione).
Inoltre quali metodi con la stessa firma possono cambiare il comportamento in contesti diversi sono forniti come dichiarazioni di interfaccia come regole da implementare di conseguenza in contesti diversi.
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 classe implementa SomeInterface, non è obbligatorio fornire l'implementazione per i metodi predefiniti dell'interfaccia.
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 permette l'estensione di più classi perché risulta nel "Diamond Problem " dove il compilatore non è in grado di decidere quale metodo della superclasse usare. Con i metodi predefiniti, il problema del diamante si presenterà anche per le interfacce. Perché se una classe implementa sia
SomeInterfaceOne and SomeInterfaceTwo
e non implementa il metodo predefinito comune, il compilatore non può decidere quale scegliere. Per evitare questo problema, in java 8 è obbligatorio implementare i metodi predefiniti comuni di diverse interfacce. Se una classe sta implementando entrambe le interfacce di cui sopra, deve fornire l'implementazione del metodo defaultMethod() altrimenti il compilatore lancerà un errore di compilazione.
La tua spiegazione sembra decente, ma forse sembrava che stessi leggendo tutto da un libro di testo? :-/
Quello che mi preoccupa di più è: quanto era solido il tuo esempio? Ti sei preoccupato di includere quasi tutte le differenze tra astratti 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
Un'interfaccia è un "contratto" dove la classe che implementa il contratto promette di implementare i metodi. Un esempio in cui ho dovuto scrivere un'interfaccia invece di una classe è stato quando stavo aggiornando un gioco dal 2D al 3D. Ho dovuto creare un'interfaccia per condividere le classi tra la versione 2D e quella 3D del gioco.
package adventure;
import java.awt.*;
public interface Playable {
public void playSound(String s);
public Image loadPicture(String s);
}
Quindi posso implementare i metodi basati sull'ambiente, pur essendo in grado di chiamare quei metodi da un oggetto che non sa quale versione del gioco sta caricando.
public class Adventure extends JFrame implements Playable
public class Dungeon3D extends SimpleApplication implements Playable
public class Main extends SimpleApplication implements AnimEventListener, ActionListener, Playable
Tipicamente, nel mondo di gioco, il mondo può essere una classe astratta che esegue metodi sul gioco:
public abstract class World...
public Playable owner;
public Playable getOwner() {
return owner;
}
public void setOwner(Playable owner) {
this.owner = owner;
}