Gli operatori is e as
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 60 di 110.
Benché runtimeType ti indichi il tipo esatto, Dart fornisce due operatori più pratici per il controllo e la conversione dei tipi: is e as.
L’operatore is verifica se un oggetto è di un tipo specifico e restituisce un booleano. A differenza di runtimeType, restituisce true anche per i tipi genitori:
class Animal {}
class Dog extends Animal {}
void main() {
Animal pet = Dog();
print(pet is Dog); // true
print(pet is Animal); // true (Dog È un Animal)
print(pet is String); // false
}Quando usi is all'interno di un'istruzione if, Dart promuove automaticamente il tipo, permettendoti di accedere ai membri della sottoclasse senza conversioni di tipo esplicite:
void handleAnimal(Animal animal) {
if (animal is Dog) {
// Qui Dart sa che animal è un Dog
animal.bark(); // Può chiamare i metodi specifici di Dog
}
}L'operatore as esegue esplicitamente il cast di un oggetto a un tipo specifico. Usalo quando sei certo del tipo:
Animal pet = Dog();
Dog myDog = pet as Dog; // Esegui il cast a Dog
myDog.bark();Fai attenzione a as: se la conversione di tipo fallisce, genera un’eccezione. Ecco perché spesso è più sicuro combinare is con la promozione del tipo invece di usare direttamente as. Puoi anche usare is! per verificare se un oggetto non è di un certo tipo.
Sfida
FacileCostruiamo un sistema di elaborazione delle forme che usa gli operatori is e as per identificare e gestire diversi tipi di forme. Creerai una gerarchia di forme e scriverai funzioni che controllano i tipi e consentono di accedere in sicurezza alle proprietà specifiche di ciascun tipo.
Organizzerai il codice in due file:
shapes.dart: definisci qui la gerarchia delle forme:- Una classe
Shapecon una proprietàString namee un costruttore. Includi un metododescribe()che stampa[name] is a shape - Una classe
Circleche estendeShapecon una proprietà aggiuntivadouble radius. Aggiungi un metodogetCircleInfo()che stampaCircle with radius: [radius] - Una classe
Rectangleche estendeShapecon le proprietà aggiuntivedouble widthedouble height. Aggiungi un metodogetRectangleInfo()che stampaRectangle: [width] x [height]
- Una classe
main.dart: importa il file delle forme e crea una funzioneprocessShape(Shape shape)che:- Per prima cosa chiama
describe()sulla forma - Usa
isper verificare se la forma è unCircle; in tal caso, usa la promozione automatica del tipo per chiamaregetCircleInfo() - Usa
isper verificare se la forma è unRectangle; in tal caso, usa l'operatoreasper eseguire il cast e chiamaregetRectangleInfo() - Usa
is!per verificare se la forma NON è unCirclee NON è unRectangle; in tal caso, stampaUnknown shape type
main():- Crea un
Circledi nome'Round'con raggio5.0e passalo aprocessShape() - Stampa una riga vuota
- Crea un
Rectangledi nome'Box'con larghezza4.0e altezza3.0e passalo aprocessShape() - Stampa una riga vuota
- Crea una
Shapedi base di nome'Mystery'e passala aprocessShape()
- Per prima cosa chiama
Questa sfida illustra entrambi gli approcci: usare is con la promozione automatica del tipo per il Circle e usare as per il cast esplicito con il Rectangle. Vedrai anche come is! aiuta a identificare le forme che non corrispondono ad alcun sottotipo specifico.
Output previsto:
Round is a shape
Circle with radius: 5.0
Box is a shape
Rectangle: 4.0 x 3.0
Mystery is a shape
Unknown shape typeProvalo tu
import 'shapes.dart';
// TODO: Crea una función processShape(Shape shape) que:
// 1. Primero llama a describe() sobre la figura
// 2. Usa 'is' para comprobar si shape es un Circle; si es así, usa la promoción de tipos para llamar a getCircleInfo()
// 3. Usa 'is' para comprobar si shape es un Rectangle; si es así, usa el operador 'as' para hacer una conversión de tipo y llamar a getRectangleInfo()
// 4. Usa 'is!' para comprobar si shape NO es un Circle NI un Rectangle; si es así, imprime "Unknown shape type"
void main() {
// TODO: Crea un Circle llamado 'Round' con radio 5.0 y pásalo a processShape()
// TODO: Imprime una línea vacía
// TODO: Crea un Rectangle llamado 'Box' con ancho 4.0 y alto 3.0, y pásalo a processShape()
// TODO: Imprime una línea vacía
// TODO: Crea un Shape base llamado 'Mystery' y pásalo a processShape()
}
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