Metodi astratti
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 44 di 110.
Un metodo astratto è un metodo dichiarato all'interno di una classe astratta che non ha un corpo. Definisce la firma del metodo, ma lascia l'implementazione a ciascuna sottoclasse. Qualsiasi classe che estende la classe astratta deve sovrascrivere tutti i metodi astratti, altrimenti sarà anch'essa astratta.
abstract class Animal {
// Metodo astratto - senza corpo, deve essere implementato dalle sottoclassi
String makeSound();
// Metodo concreto - ha un corpo, condiviso da tutte le sottoclassi
void breathe() {
print('Breathing...');
}
}
class Dog extends Animal {
@override
String makeSound() {
return 'Woof!'; // Deve fornire un'implementazione
}
}
class Cat extends Animal {
@override
String makeSound() {
return 'Meow!'; // Implementazione diversa, stessa firma
}
}Se una sottoclasse dimentica di implementare un metodo astratto, Dart ti segnalerà un errore di compilazione. Questo è proprio il punto: i metodi astratti impongono un contratto. È garantito che ogni sottoclasse abbia quel metodo, quindi puoi chiamarlo in sicurezza su qualsiasi istanza del tipo astratto.
// Puoi usare il tipo astratto come tipo di una variabile
Animal a = Dog();
print(a.makeSound()); // Bau!
Animal b = Cat();
print(b.makeSound()); // Miao!I metodi astratti sono diversi dai metodi concreti in una classe astratta. I metodi concreti hanno un corpo e vengono ereditati così come sono. I metodi astratti non hanno un corpo e devono essere sovrascritti.
Puoi combinarli entrambi nella stessa classe astratta per condividere alcuni comportamenti, obbligando al contempo le sottoclassi a definirne di propri per gli altri.
| Caratteristica | Metodo astratto | Metodo concreto |
|---|---|---|
| Ha un corpo | No | Sì |
| Deve essere sovrascritto | Sì | No |
| Scopo | Imporre un contratto | Condividere il comportamento |
| Dove | Solo nelle classi astratte | Qualsiasi classe |
Sfida
FacileCostruiamo un calcolatore di forme che mostri in azione i metodi astratti. Definirai una classe astratta con metodi astratti che ogni forma dovrà implementare in modo diverso, poi userai queste forme tramite un'interfaccia comune.
Organizzerai il codice in quattro file:
shape.dart: Definisci una classe astrattaShapecon un campofinalcolor(String) e un costruttore che lo inizializza. Dichiara due metodi astratti:double area()edouble perimeter(). Aggiungi anche un metodo concretodescribe()che stampaA [color] shape with area: [area] and perimeter: [perimeter]. Poichéarea()eperimeter()sono astratti, ogni sottoclasse fornirà il proprio calcolo, madescribe()funziona per tutte senza essere sovrascritto.circle.dart: Crea una classeCircleche estendeShape. Ha un campofinalradius(double). Il suo costruttore accettacoloreradiuse passacolorasuper. Implementaarea()in modo che restituisca3.14 * radius * radiuseperimeter()in modo che restituisca2 * 3.14 * radius.rectangle.dart: Crea una classeRectangleche estendeShape. Ha i campifinalwidtheheight(entrambi double). Il suo costruttore accettacolor,widtheheighte passacolorasuper. Implementaarea()in modo che restituiscawidth * heighteperimeter()in modo che restituisca2 * (width + height).main.dart: Importa tutti i file. Crea unCirclecon colore'red'e raggio5.0, e unRectanglecon colore'blue', larghezza4.0e altezza6.0. Chiamadescribe()su ciascuna forma. Poi crea unaList<Shape>contenente entrambe le forme, scorri la lista e stampaArea: [area]per ciascuna forma.
Output previsto:
A red shape with area: 78.5 and perimeter: 31.400000000000002
A blue shape with area: 24.0 and perimeter: 20.0
Area: 78.5
Area: 24.0Provalo tu
import 'shape.dart';
import 'circle.dart';
import 'rectangle.dart';
void main() {
// TODO: Crea un Circle con colore 'red' e raggio 5.0
// TODO: Crea un Rectangle con colore 'blue', larghezza 4.0 e altezza 6.0
// TODO: Chiama describe() sul cerchio
// TODO: Chiama describe() sul rettangolo
// TODO: Crea una List<Shape> che contenga entrambe le forme
// TODO: Scorri la lista e stampa "Area: [area]" per ogni forma
}
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