Differenza tra classe Abstact e interfaccia
- Classi astratte contro interfacce in Java 8
- Differenza concettuale:
Metodi predefiniti dell'interfaccia in Java 8
- Cos'è il metodo predefinito?
- Ogni errore di compilazione del metodo è stato risolto utilizzando il metodo predefinito
- Metodo predefinito e problemi di ambiguità dell'ereditarietà multipla
- Punti importanti sui metodi predefiniti dell'interfaccia java:
Metodo statico dell'interfaccia Java
- Metodo statico dell'interfaccia Java, esempio di codice, metodo statico vs metodo predefinito
- 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 concetto diverso in Java 8.
La classe astratta può definire il costruttore. Sono più strutturati e possono avere uno stato ad essi associato. Al contrario, il metodo predefinito può essere implementato solo in termini di invocazione di altri metodi di interfaccia, senza alcun riferimento allo stato di una particolare implementazione. Quindi, entrambi usano per scopi diversi e la scelta tra due dipende davvero 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 corrispondente.
Quindi, quando le classi astratte vengono effettivamente ridotte in implementazioni scheletriche di interfacce a bassa visibilità, anche i metodi predefiniti possono portarlo via? Decisamente: no! L'implementazione delle interfacce richiede quasi sempre alcuni o tutti quegli strumenti per la creazione di classi di cui mancano i metodi predefiniti. E se un'interfaccia non lo fa, è chiaramente un caso speciale, che non dovrebbe farti smarrire.
Metodi predefiniti dell'interfaccia 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 a Interface di definire l'implementazione che utilizzerà come impostazione predefinita nella situazione in cui una Classe concreta non riesce a fornire un'implementazione per quel metodo.
Consideriamo 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 classe 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();
I metodi predefiniti non sono mai definitivi, non possono essere sincronizzati e non possono ignorare 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 definito con l'implementazione non viene influenzata alcuna classe di implementazione. Una classe 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 le seguenti operazioni,
- Non sovrascrivere il metodo predefinito ed erediterà il metodo predefinito.
- Sostituisci il metodo predefinito simile ad altri metodi che sostituiamo nella sottoclasse.
- Ridichiarare il metodo predefinito come astratto, che forza la sottoclasse a sovrascriverlo.
Ogni errore di compilazione del metodo è stato risolto utilizzando il metodo predefinito
Per Java 8, le raccolte JDK sono state estese e ogni metodo è stato aggiunto all'intera raccolta (che funziona in combinazione con lambdas). Con il modo convenzionale, il codice appare come di seguito,
public interface Iterable<T> {
public void forEach(Consumer<? super T> consumer);
}
Dal momento che questo risultato ogni classe di implementazione con errori di compilazione, quindi, è stato aggiunto un metodo predefinito con un'implementazione richiesta in modo che l'implementazione esistente non debba essere modificata.
L'interfaccia Iterable con il metodo predefinito è di seguito,
public interface Iterable<T> {
public default void forEach(Consumer
<? super T> consumer) {
for (T t : this) {
consumer.accept(t);
}
}
}
Lo stesso meccanismo è stato utilizzato per aggiungere Stream nell'interfaccia JDK senza interrompere le Classi di implementazione.
Metodo predefinito e problemi di ambiguità dell'ereditarietà multipla
Poiché la classe java può implementare più interfacce e ciascuna interfaccia può definire il metodo predefinito con la stessa firma del metodo, pertanto i metodi ereditati possono entrare in conflitto tra loro.
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 riportato non verrà compilato con il seguente errore,
java: classe Impl eredita impostazioni predefinite non correlate per defaultMethod () dai tipi InterfaceA e InterfaceB
Per correggere questa classe, dobbiamo 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 dalla nostra stessa implementazione, possiamo farlo come segue,
public class Impl implements InterfaceA, InterfaceB {
public void defaultMethod(){
// existing code here..
InterfaceA.super.defaultMethod();
}
}
Possiamo scegliere qualsiasi implementazione predefinita o entrambe come parte del nostro nuovo metodo.
Punti importanti sui metodi predefiniti dell'interfaccia java:
- I metodi predefiniti dell'interfaccia Java ci aiuteranno a estendere le interfacce senza temere di interrompere le classi di implementazione.
- I metodi predefiniti dell'interfaccia Java hanno colmato le differenze tra interfacce e classi astratte.
- I metodi predefiniti dell'interfaccia Java 8 ci aiuteranno a evitare le classi di utilità, come tutto il metodo della classe Collections può essere fornito nelle interfacce stesse.
- I metodi predefiniti dell'interfaccia Java ci aiuteranno a rimuovere le classi di implementazione di base, possiamo fornire l'implementazione di default e le classi di implementazione possono scegliere quale sovrascrivere.
- Uno dei motivi principali per l'introduzione di metodi predefiniti nelle interfacce è quello di migliorare l'API Collections in Java 8 per supportare le espressioni lambda.
- Se una classe 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 classe base per tutte le classi java. Quindi, anche se abbiamo metodi della classe Object definiti come metodi predefiniti nelle interfacce, sarà inutile perché verrà sempre usato il metodo della classe Object. Ecco perché per evitare confusione, non possiamo avere metodi predefiniti che sovrascrivono i metodi della classe Object.
- I metodi predefiniti dell'interfaccia Java sono anche definiti Metodi Defender o Metodi di estensione virtuale.
Collegamento alle risorse:
- Interfaccia con metodi predefiniti vs classe astratta in Java 8
- Classe astratta contro interfaccia nell'era JDK 8
- Evoluzione dell'interfaccia tramite metodi di estensione virtuale
Metodo statico dell'interfaccia Java
Metodo statico dell'interfaccia Java, esempio di codice, metodo statico vs metodo predefinito
Il metodo statico dell'interfaccia Java è simile al metodo predefinito, tranne per il fatto che non possiamo sostituirli nelle classi di implementazione. Questa funzionalità ci aiuta a 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;
}
}
Vediamo ora una classe di implementazione che ha 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");
}
}
Nota che isNull (String str) è un metodo di classe semplice, non ha la precedenza sul metodo di interfaccia. Ad esempio, se aggiungeremo l'annotazione @Override al metodo isNull (), si verificherà un errore del compilatore.
Ora quando eseguiremo l'applicazione, otteniamo il seguente output.
Controllo null interfaccia
Controllo null impl
Se rendiamo il metodo dell'interfaccia da statico a predefinito, otterremo il seguente output.
Controllo null impl
MyData Print ::
Controllo null impl
Il metodo statico dell'interfaccia Java è visibile solo per i metodi di interfaccia, se rimuoviamo il metodo isNull () dalla classe MyDataImpl, non saremo in grado di usarlo per l'oggetto MyDataImpl. Tuttavia, come altri metodi statici, possiamo usare i metodi statici dell'interfaccia usando il nome della classe. Ad esempio, un'istruzione valida sarà:
boolean result = MyData.isNull("abc");
Punti importanti sul metodo statico dell'interfaccia java:
- Il metodo statico dell'interfaccia Java fa parte dell'interfaccia, non possiamo usarlo per gli oggetti della classe di implementazione.
- I metodi statici dell'interfaccia Java sono utili per fornire metodi di utilità, ad esempio controllo null, ordinamento delle raccolte ecc.
- Il metodo statico dell'interfaccia Java ci aiuta a fornire sicurezza impedendo alle classi di implementazione di sovrascriverle.
- Non possiamo definire il metodo statico dell'interfaccia per i metodi della classe Object, otterremo un errore del compilatore come "Questo metodo statico non può nascondere il metodo dell'istanza da Object". Questo perché non è consentito in Java, poiché Object è la classe di base per tutte le classi e non possiamo avere un metodo statico a livello di classe e un altro metodo di istanza con la stessa firma.
- Possiamo usare i metodi statici dell'interfaccia java per rimuovere le classi di utilità come Collezioni e spostare tutti i suoi metodi statici sull'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.
È @FunctionalInterface
stata introdotta una nuova annotazione per contrassegnare un'interfaccia come interfaccia funzionale.@FunctionalInterface
l'annotazione è una funzione per evitare l'aggiunta accidentale di metodi astratti nelle interfacce funzionali. È facoltativo ma buona pratica usarlo.
Le interfacce funzionali sono attese da tempo e sono molto ricercate funzionalità di Java 8 perché ci consente di usare espressioni lambda per istanziarle. Un nuovo pacchetto java.util.function con un sacco di interfacce funzionali viene aggiunto per fornire tipi di destinazione per espressioni lambda e riferimenti a metodi. Esamineremo le interfacce funzionali e le espressioni lambda nei post futuri.
Ubicazione delle risorse:
- Modifiche all'interfaccia Java 8: metodo statico, metodo predefinito