Interfacce in Dart
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 45 di 110.
A differenza di molti linguaggi che hanno una parola chiave interface dedicata, Dart adotta un approccio diverso. In Dart, ogni classe definisce automaticamente un’interfaccia. Questa interfaccia è composta da tutti i membri pubblici (metodi e proprietà) dichiarati dalla classe.
Quando vuoi che una classe prometta di fornire determinate funzionalità senza ereditare un'implementazione, usi la parola chiave implements:
class Printer {
void printDocument(String content) {
print('Printing: $content');
}
}
class Scanner {
void scan() {
print('Scanning document');
}
}
// MultiFunctionDevice deve implementare TUTTI i metodi di entrambe le classi
class MultiFunctionDevice implements Printer, Scanner {
@override
void printDocument(String content) {
print('MFD printing: $content');
}
@override
void scan() {
print('MFD scanning');
}
}La differenza fondamentale rispetto a extends è che implements non eredita alcun codice. Devi fornire la tua implementazione per ogni metodo e proprietà definiti nell’interfaccia. È un contratto: prometti che la tua classe avrà queste capacità, ma decidi tu esattamente come funzionano.
Questo approccio offre flessibilità a Dart. Puoi usare classi astratte quando vuoi definire interfacce senza implementazione, oppure usare classi normali come interfacce quando ha senso. La prossima lezione esplora più nel dettaglio come funziona questo concetto di «interfaccia implicita».
Sfida
FacileCostruiamo un sistema di riproduzione multimediale che dimostri come funziona la parola chiave implements in Dart. Creerai classi che fungono da interfacce e poi le implementerai in un unico dispositivo che combina più funzionalità.
Organizzerai il codice in due file:
media.dart: definisci qui le classi interfaccia e la classe che le implementa:- Una classe
AudioPlayercon un metodoplayAudio(String track)che stampaPlaying audio: [track] - Una classe
VideoPlayercon un metodoplayVideo(String title)che stampaPlaying video: [title] - Una classe
SmartTVche implementa siaAudioPlayersiaVideoPlayer. Poichéimplementsnon eredita alcun codice, devi fornire implementazioni personalizzate per entrambi i metodi. La tua classeSmartTVdeve stampareSmartTV audio: [track]per l'audio eSmartTV video: [title]per il video
- Una classe
main.dart: importa il file multimediale e mostra come una singola classe possa implementare più interfacce:- Crea un'istanza di
SmartTV - Chiama
playAudio('Jazz Collection') - Chiama
playVideo('Nature Documentary')
- Crea un'istanza di
Nota come SmartTV debba fornire una propria implementazione per ogni metodo di entrambe le interfacce: non eredita le implementazioni originali da AudioPlayer o VideoPlayer. Questa è la differenza fondamentale tra implements e extends.
Output previsto:
SmartTV audio: Jazz Collection
SmartTV video: Nature DocumentaryProvalo tu
import 'media.dart';
void main() {
// TODO: Crea un'istanza di SmartTV
// TODO: Chiama playAudio('Jazz Collection')
// TODO: Chiama playVideo('Nature Documentary')
}
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 orientata agli oggetti
File esterniLibrerie e importazioniIntroduzione alla programmazione orientata agli oggettiClassi e oggettiLa parola chiave thisMetodiVariabili di istanzaFondamenti dei costruttoriRiepilogo - Calcolatrice semplice4Sicurezza dei valori null
Introduzione alla sicurezza dei valori nullNullable e non nullableGli operatori ? e !La keyword late e la sicurezza dei valori nullOperatori null-awareSicurezza dei valori null nelle classiRiepilogo - Sistema di profili utente7Classi astratte e interfacce
Classi astratteMetodi astrattiInterfacce in DartInterfacce impliciteImplementare vs estendereInterfacce multipleRiepilogo - Calcolatore di forme10Collezioni e generici
Panoramica di List, Set e MapCollezioni sicure rispetto ai tipiClassi genericheMetodi genericiVincoli sui genericiIterable e IteratorRiepilogo - Archiviazione generica13Concetti avanzati di OOP
Composizione vs ereditarietàMetodi di estensioneClassi chiamabiliClassi sealed (Dart 3)Record (Dart 3)Pattern e matching (3.0)Enum con metodi16Progetto: Gestione della biblioteca
Panoramica del progettoClassi Libro e Utente2I costruttori in Dart
Costruttore predefinitoCostruttori con nomeListe di inizializzazioneCostruttori costantiCostruttori factoryCostruttori di reindirizzamentoRiepilogo - Crea forme5Incapsulamento
Membri pubblici e privatiConvenzione del prefisso _Visibilità a livello di libreriaApprofondimento su getter e setterNascondimento delle informazioniRiepilogo - Registri degli studenti8Mixin
Introduzione ai MixinCreare MixinUsare più MixinParola chiave on nei MixinMixin vs ereditarietàMixin vs interfacciaRiepilogo - Sistema animale11Metodi speciali
Sovrascrittura di toString()Sovrascrittura di hashCode e ==Interfaccia ComparableMetodo call()Sovrascrittura di noSuchMethodRiepilogo - Collezione personalizzata14Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneSingletonFactoryObserverStrategy3Proprietà delle classi
Membri di istanza e staticiCampi final e constVariabili lateMetodi e campi staticiGetter e setterRiepilogo - Gestore di conti bancari6Ereditarietà
Ereditarietà di baseLa parola chiave superOverride dei metodiL’annotazione @overrideLa parola chiave final per le classiCostruttori ed ereditarietàRiepilogo - Gerarchia dei dipendenti9Polimorfismo
Fondamenti di polimorfismoPolimorfismo tramite interfacceControllo del tipo a runtimeGli operatori is e asParola chiave covariantRiepilogo - Elaboratore di pagamenti12OOP asincrona
Future e async/awaitNozioni di base sugli streamController degli streamCostruttori asincroniAsync nei metodi di classeRiepilogo - Recupero dei dati15Pattern di progettazione Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositePattern RepositoryEsercitati da solo: Compilatore Dart online