Menu
Coddy logo textTech

Sealed Classes (Dart 3)

Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 85 von 110.

Dart 3 hat Sealed Classes eingeführt, die einschränken, welche Klassen sie erweitern oder implementieren können. Wenn Sie eine Klasse als sealed markieren, können nur Klassen in derselben Datei ihre direkten Untertypen sein. Dies erstellt eine geschlossene Menge bekannter Untertypen.

sealed class Result {}

class Success extends Result {
  final String data;
  Success(this.data);
}

class Failure extends Result {
  final String error;
  Failure(this.error);
}

Die Stärke von sealed classes liegt in der Vollständigkeitsprüfung (exhaustiveness checking). Wenn Sie ein switch über einen sealed type ausführen, kennt der Compiler alle möglichen Subtypen und stellt sicher, dass Sie jeden einzelnen behandeln:

String handleResult(Result result) {
  return switch (result) {
    Success(data: var d) => 'Got: $d',
    Failure(error: var e) => 'Error: $e',
  };
  // Kein Default erforderlich – der Compiler weiß, dass alle Fälle abgedeckt sind!
}

void main() {
  var success = Success('Hello');
  var failure = Failure('Not found');
  
  print(handleResult(success));  // Got: Hello
  print(handleResult(failure));  // Error: Not found
}

Wenn Sie einer sealed class einen neuen Subtyp hinzufügen, wird der Compiler jede switch-Anweisung markieren, die diesen nicht berücksichtigt. Dies macht sealed classes ideal für die Modellierung von Zuständen, Ergebnissen oder anderen Szenarien, in denen eine feste Anzahl von Varianten vorliegt. Im Gegensatz zu abstract classes garantieren sealed classes, dass kein externer Code unerwartete Subtypen hinzufügen kann.

challenge icon

Aufgabe

Einfach

Lassen Sie uns einen Netzwerk-Request-Handler mit versiegelten Klassen (sealed classes) erstellen! Sie werden ein typsicheres System entwickeln, das verschiedene Zustände einer Netzwerkantwort modelliert und sicherstellt, dass jedes mögliche Ergebnis ordnungsgemäß verarbeitet wird.

Sie werden Ihren Code in zwei Dateien organisieren:

  • response.dart: Erstellen Sie eine versiegelte Klassenhierarchie, die alle möglichen Zustände einer Netzwerkantwort darstellt:
    • Eine versiegelte Klasse namens NetworkResponse, die als Basis für alle Antworttypen dient
    • Eine Loading-Klasse, die NetworkResponse erweitert und ein String message-Feld enthält (z. B. "Fetching data...")
    • Eine Success-Klasse, die NetworkResponse erweitert und ein String data-Feld sowie ein int statusCode-Feld enthält
    • Eine Error-Klasse, die NetworkResponse erweitert und ein String errorMessage-Feld sowie ein int errorCode-Feld enthält
  • main.dart: Importieren Sie Ihre Response-Datei und erstellen Sie eine Funktion, die alle Antworttypen mithilfe eines Switch-Ausdrucks verarbeitet:
    • Erstellen Sie eine Funktion handleResponse(NetworkResponse response), die einen String zurückgibt
    • Verwenden Sie einen Switch-Ausdruck mit Pattern Matching, um jeden Fall zu behandeln:
      • Für Loading: geben Sie Status: [message] zurück
      • Für Success: geben Sie Success ([statusCode]): [data] zurück
      • Für Error: geben Sie Error ([errorCode]): [errorMessage] zurück
    • Erstellen Sie drei Response-Instanzen und geben Sie das Ergebnis der Verarbeitung jeder Instanz aus:
      • Ein Loading mit der Nachricht Please wait...
      • Ein Success mit den Daten User profile loaded und dem Statuscode 200
      • Ein Error mit der Fehlermeldung Not found und dem Fehlercode 404

Das Schöne an versiegelten Klassen ist, dass der Compiler sicherstellt, dass Sie jeden möglichen Antworttyp behandeln - ein Default-Case ist nicht erforderlich!

Erwartete Ausgabe:

Status: Please wait...
Success (200): User profile loaded
Error (404): Not found

Probier es selbst

import 'response.dart';

// TODO: Erstelle eine Funktion handleResponse(NetworkResponse response)
// die einen String zurückgibt
// Verwende einen switch-Ausdruck mit Pattern Matching, um jeden Fall zu behandeln:
// - Für Loading: gib "Status: [message]" zurück
// - Für Success: gib "Success ([statusCode]): [data]" zurück
// - Für Error: gib "Error ([errorCode]): [errorMessage]" zurück

void main() {
  // TODO: Erstelle eine Loading-Instanz mit der Nachricht "Please wait..."
  
  // TODO: Erstelle eine Success-Instanz mit den Daten "User profile loaded" und dem Statuscode 200
  
  // TODO: Erstelle eine Error-Instanz mit der Fehlermeldung "Not found" und dem Fehlercode 404
  
  // TODO: Gib das Ergebnis der Verarbeitung jeder Antwort aus
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung