Metodi default e static nelle interfacce
Fa parte della sezione Programmazione orientata agli oggetti del percorso Java di Coddy. Lezione 37 di 87.
In origine, le interfacce potevano contenere solo metodi astratti senza implementazione. A partire da Java 8, le interfacce hanno acquisito la possibilità di includere metodi predefiniti e metodi statici, diventando così più flessibili.
Un metodo predefinito fornisce un’implementazione direttamente nell’interfaccia usando la parola chiave default. Le classi che implementano l’interfaccia ereditano automaticamente questo comportamento, ma possono sovrascriverlo se necessario:
public interface Drawable {
void draw();
default void display() {
System.out.println("Displaying on screen...");
draw();
}
}Qualsiasi classe che implementa Drawable ottiene gratuitamente il metodo display(). Questo è particolarmente utile per aggiungere nuovi metodi alle interfacce esistenti senza compromettere le classi che le implementano già.
I metodi statici nelle interfacce funzionano come i metodi statici nelle classi. Appartengono all'interfaccia stessa e vengono chiamati usando il nome dell'interfaccia:
public interface MathOperations {
static int add(int a, int b) {
return a + b;
}
}
// Utilizzo
int result = MathOperations.add(5, 3);I metodi statici dell'interfaccia non possono essere sovrascritti e non vengono ereditati dalle classi che la implementano. Sono utili per i metodi di utilità legati allo scopo dell'interfaccia.
Se una classe implementa due interfacce con la stessa firma di metodo predefinito, la classe deve sovrascrivere quel metodo per risolvere il conflitto.
Sfida
FacileCostruiamo un sistema di messaggistica che mostri sia i metodi predefiniti sia quelli statici nelle interfacce. Creerai un’interfaccia con funzionalità integrate che le classi che la implementano possono usare direttamente o personalizzare secondo necessità.
Organizzerai il codice in quattro file:
Messenger.java: Definisci un’interfaccia che rappresenta qualsiasi servizio di messaggistica. Deve dichiarare un metodo astrattosendMessage(String message)che restituisce void. Aggiungi un metodo predefinito chiamatosendWithTimestamp(String message)che stampa:[TIMESTAMP]e poi chiamasendMessage(message). Includi anche un metodo statico chiamatoformatMessage(String message)che restituisce il messaggio convertito in maiuscolo.EmailMessenger.java: Crea una classe che implementaMessenger. Ha un camporecipient(String). Includi un costruttore per inizializzare recipient. ImplementasendMessage()in modo che stampi:Email to [recipient]: [message]. Questa classe usa così com’è il metodo predefinitosendWithTimestamp().SMSMessenger.java: Crea un’altra classe che implementaMessenger. Ha un campophoneNumber(String). Includi un costruttore per inizializzare il numero di telefono. ImplementasendMessage()in modo che stampi:SMS to [phoneNumber]: [message]. Sovrascrivi il metodo predefinitosendWithTimestamp()in modo che stampi:[URGENT]e poi chiamisendMessage(message), invece di usare il comportamento predefinito con timestamp.Main.java: Metti insieme tutti gli elementi per mostrare sia i metodi predefiniti sia quelli statici delle interfacce. Riceverai tre input: un destinatario email, un numero di telefono e un messaggio. Per prima cosa, usa il metodo staticoMessenger.formatMessage()per formattare il messaggio e memorizzarlo. Poi crea un EmailMessenger e un SMSMessenger. Per ciascun messenger, chiamasendWithTimestamp()con il messaggio formattato: nota come EmailMessenger usa l’implementazione predefinita, mentre SMSMessenger usa la sua versione sovrascritta.
Riceverai tre input: il destinatario email (String), il numero di telefono (String) e il messaggio (String).
L’output deve mostrare quattro righe in totale, due per ciascun messenger: una riga con il prefisso ([TIMESTAMP] o [URGENT]) seguita dalla riga con il messaggio. EmailMessenger mostrerà il prefisso predefinito con timestamp, mentre SMSMessenger mostrerà il suo prefisso personalizzato di urgenza. Entrambi useranno il messaggio formattato staticamente (in maiuscolo)!
Provalo tu
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Leggi i dati in input
String emailRecipient = scanner.nextLine();
String phoneNumber = scanner.nextLine();
String message = scanner.nextLine();
// TODO: Usa Messenger.formatMessage() per formattare il messaggio e memorizzarlo
// TODO: Crea un EmailMessenger con il destinatario dell'email
// TODO: Crea un SMSMessenger con il numero di telefono
// TODO: Chiama sendWithTimestamp() su EmailMessenger con il messaggio formattato
// TODO: Chiama sendWithTimestamp() su SMSMessenger con il messaggio formattato
}
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione a oggetti
File esterniIntroduzione alla programmazione a oggettiClassi e oggettiLa parola chiave thisMetodiCampi (attributi)Metodo costruttoreSovraccarico dei costruttoriRipasso - Calcolatrice semplice4Ereditarietà
Ereditarietà di base (extends)La parola chiave superSovrascrittura dei metodi (@Override)Concatenamento dei costruttoriLa classe ObjectEreditarietà singola e multilivelloPerché non esiste l'ereditarietà multipla delle classiRiepilogo: gerarchia dei dipendenti7Metodi speciali e classe Object
Metodo toString()equals() e hashCode()Metodo clone()compareTo() e ComparableInterfaccia ComparatorRiepilogo - Ordinamento personalizzato2Modificatori di accesso e incapsulamento
Panoramica dei livelli di accessoMetodi getter e setterNascondimento delle informazioniLa parola chiave finalRiepilogo - Gestore di conti bancari5Polimorfismo
Nozioni di base sull'overloading dei metodiOverride dei metodi (a runtime)Upcasting e downcastingL'operatore instanceofClassi e metodi astrattiRiepilogo - Calcolatore di forme8Concetti avanzati di OOP
Composizione vs ereditarietàAggregazione vs composizioneClassi interne, annidate e anonimeEnum e metodi degli EnumRecord (Java 16+)Classi sealed (Java 17+)11Modelli di progettazione Parte 1
Introduzione ai modelli di progettazionePattern SingletonPattern FactoryPattern BuilderPattern ObserverPattern Strategy3Proprietà di classe e membri statici
Variabili di istanza e staticheMetodi staticiBlocchi staticiCostanti (static final)Riepilogo - Contatore e utility6Interfacce e classi astratte
Introduzione alle interfacceImplementazione delle interfacceImplementazione di più interfacceMetodi default e static nelle interfacceClassi astratte e interfacce a confrontoInterfacce funzionaliRiepilogo: sistema di pagamento9Tipi generici
Introduzione ai tipi genericiClassi genericheMetodi genericiParametri di tipo con limitiCaratteri jolly (?, extends, super)Riepilogo - Contenitore generico12Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositePattern IteratorEsercitati da solo: Compilatore Java online