Dart Enums und Symbole

Ein Enum wird verwendet, um eine Menge benannter konstanter Werte zu definieren, wodurch der Code lesbarer wird.

Dieses Kapitel führt in die Definition von Dart-Enums, erweiterten Enums (mit Methoden und Eigenschaften) sowie die Typen Symbol und Rune ein.


enum Enum-Definition

Ein Enum ist eine spezielle Art von Klasse, die verwendet wird, um eine feste Anzahl konstanter Werte darzustellen.

Die typischsten Szenarien sind die Darstellung endlicher Optionen wie Zustände, Richtungen, Farben usw.

Beispiel

// Ein Enum definieren
enum Status {
  pending,    // Ausstehend
  approved,   // Genehmigt
  rejected,   // Abgelehnt
  cancelled,  // Storniert
}

void main() {
  // Enum-Werte verwenden
  Status currentStatus = Status.pending;
  print('Aktueller Status: $currentStatus');

  // Den Index über .index abrufen (beginnend bei 0)
  print('Indexwert: ${currentStatus.index}');  // 0

  // Alle Enum-Werte über .values abrufen
  print(Alle Status: ${Status.values});

  // Alle Enum-Werte durchlaufen
  for (var status in Status.values) {
    print(BEISPIEL Status: $status, Index: ${status.index});
  }

  // Enum-Wert per String abrufen
  Status parsed = Status.values.byName('approved');
  print(Geparster Status: $parsed);

  // Enums in switch verwenden
  switch (currentStatus) {
    case Status.pending:
      print(Bestellung ausstehend);
      break;
    case Status.approved:
      print(Bestellung genehmigt);
      break;
    case Status.rejected:
      print(Bestellung abgelehnt);
      break;
    case Status.cancelled:
      print(Bestellung storniert);
      break;
  }
}
当前状态: Status.pending
索引值: 0
所有状态: [Status.pending, Status.approved, Status.rejected, Status.cancelled]
EXAMPLE 状态: Status.pending, 索引: 0
EXAMPLE 状态: Status.approved, 索引: 1
EXAMPLE 状态: Status.rejected, 索引: 2
EXAMPLE 状态: Status.cancelled, 索引: 3
解析出的状态: Status.approved
订单待处理

Enums und switch sind ein perfektes Paar. Wenn du alle Enum-Werte in einem switch behandelst, prüft der Dart-Compiler, ob du alle Fälle abgedeckt hast. Das vermeidet Fehler durch fehlende Zweige.


Erweiterte Enums (mit Methoden und Eigenschaften)

Dart 3.0 führte erweiterte Enums ein, die es Enums ermöglichen, Felder, Methoden und Konstruktoren zu haben.

Beispiel

// Erweitertes Enum: kann Membervariablen, Konstruktoren und Methoden haben
enum HttpStatus {
  // Enum-Werte übergeben Parameter über den Konstruktor
  ok(200, Anfrage erfolgreich),
  created(201, Ressource erstellt),
  badRequest(400, Ungültige Anfrage),
  unauthorized(401, Nicht autorisiert),
  notFound(404, Ressource nicht gefunden),
  serverError(500, Interner Serverfehler);

  // Mitgliedsvariablen: Jeder enum-Wert hat code und message
  final int code;
  final String message;

  // Konstruktor: muss const sein
  const HttpStatus(this.code, this.message);

  // Enum-Methode
  bool get isSuccess => code >= 200 && code < 300;
  bool get isClientError => code >= 400 && code < 500;
  bool get isServerError => code >= 500;

  // Statische Methode: Enum anhand des Statuscodes finden
  static HttpStatus? fromCode(int code) {
    try {
      return HttpStatus.values.firstWhere((s) => s.code == code);
    } catch (_) {
      return null;
    }
  }
}

void main() {
  var status = HttpStatus.notFound;

  print(BEISPIEL HTTP-Status: $status);
  print(Statuscode: ${status.code});
  print(Meldung: ${status.message});
  print(Ist erfolgreich: ${status.isSuccess});
  print('Ist Client-Fehler: ${status.isClientError}');

  // Nachschlagen mit einer statischen Methode
  var found = HttpStatus.fromCode(201);
  if (found != null) {
    print('Gefundener Status: ${found.message}');
  }

  var unknown = HttpStatus.fromCode(999);
  print('Unbekannter Statuscode: $unknown');
}
EXAMPLE HTTP 状态: HttpStatus.notFound
状态码: 404
Message: 资源未找到
是否成功: false
是否客户端错误: true
找到状态: 资源已创建
未知状态码: null

Erweiterte Enums erheben Enums von "Sammlungen benannter Konstanten" zu "Typen mit Verhalten", wodurch sie Logik im Zusammenhang mit dem Enum kapseln können.

Die Konstruktoren erweiterter Enums müssen const sein, und Membervariablen müssen final sein. Das liegt daran, dass Enum-Werte selbst Kompilierzeitkonstanten sind.


Symbol-Typ

Symbol repräsentiert Bezeichner in Dart-Programmen (Variablennamen, Funktionsnamen usw.).

Es wird im täglichen Entwicklungsalltag nicht häufig verwendet; es wird hauptsächlich in Reflexions- und Codegenerierungsszenarien eingesetzt.

Beispiel

void main() {
  // Verwende das Präfix #, um ein Symbol zu erstellen
  Symbol sym1 = #example;
  Symbol sym2 = #helloWorld;

  print('Symbol 1: $sym1');  // Symbol("example")
  print('Symbol 2: $sym2');  // Symbol("helloWorld")

  // Symbol-Vergleich
  Symbol sym3 = #example;
  print('sym1 == sym3: ${sym1 == sym3}');  // true

  // Symbol kann als Map-Schlüssel verwendet werden
  var metadata = {
    #author: 'EXAMPLE',
    #version: '1.0.0',
    #description: Dart-Tutorial,
  };
  print('Autor: ${metadata[#author]}');
}
Symbol 1: Symbol("example")
Symbol 2: Symbol("helloWorld")
sym1 == sym3: true
作者: EXAMPLE

Symbole werden nach der Dart-Kompilierung normalerweise minifiziert, daher sollte man sich für logische Entscheidungen nicht auf das Ergebnis von Symbol("example").toString() verlassen. Die korrekte Verwendung von Symbol dient Reflexionsoperationen über die Bibliothek dart:mirrors.


Runes und Unicode

Rune ist der Typ in Dart, der Unicode-Codepunkte repräsentiert.

In Dart sind Strings in UTF-16 kodierte Sequenzen.

Für Zeichen außerhalb der Basic Multilingual Plane (BMP), wie z. B. Emojis, wird Rune benötigt, um sie zu verarbeiten.

Beispiel

void main() {
  // Die Unicode-Codepunkte des Strings abrufen
  String text = 'EXAMPLE';
  print('Character: $text');
  print('Code point list: ${text.runes.toList()}');

  // Über jedes Zeichen und seinen Codepunkt iterieren
  for (var char in text.runes) {
    print('${String.fromCharCode(char)} -> U+${char.toRadixString(16).toUpperCase().padLeft(4, '0')}');
  }

  // Ein Zeichen aus einem Codepunkt erstellen
  var heart = String.fromCharCode(0x2764);
  print('Herz: $heart');

  // Mehrfach-Codepunkt-Zeichen behandeln (wie einige Emojis)
  var smile = '\u{1F600}';  // Verwende die \u{}-Syntax, um Zeichen außerhalb der BMP darzustellen
  print('Smiley: $smile');

  // Die Codepunkte eines Zeichens mit mehreren Codepunkten abrufen
  print('Smiley-Codepunkte: ${smile.runes.map((r) => 'U+${r.toRadixString(16).toUpperCase()}').toList()}');
}
字符: EXAMPLE
码点列表: [82, 85, 78, 79, 79, 66]
R -> U+0052
U -> U+0055
N -> U+004E
O -> U+004F
O -> U+004F
B -> U+0042
心形: &#x2764;
笑脸: &#x1f600;
笑脸码点: [U+1F600]

In der alltäglichen Entwicklung müssen Sie nicht direkt mit Rune arbeiten; Strings selbst kommen gut mit Unicode zurecht.

Rune wird hauptsächlich verwendet, wenn eine präzise Manipulation von Zeichen-Codepunkten erforderlich ist, z. B. in Low-Level-Szenarien wie Texteditoren und Schriftrendering.

Weitere Erweiterungen