EMZETT.
Login

Kurz: Konto(this.inhaber, [this._stand = 0]) { // Kurzform: Parameter direkt in Felder anzahl++; }

Teil des Kurses Dart

Kapitel 4 von 8 im Kurs Dart (Abschnitt „Objektorientierung“). Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Klassen

class Konto {
  final String inhaber;
  double _stand;                       // _ macht Member privat (pro Datei)
  static int anzahl = 0;
 
  Konto(this.inhaber, [this._stand = 0]) {      // Kurzform: Parameter direkt in Felder
    anzahl++;
  }
 
  Konto.leer(String inhaber) : this(inhaber, 0);          // benannter Konstruktor
 
  double get stand => _stand;                              // Getter
  set stand(double wert) {                                 // Setter mit Prüfung
    if (wert < 0) throw ArgumentError('Stand darf nicht negativ sein');
    _stand = wert;
  }
 
  void einzahlen(double betrag) {
    if (betrag <= 0) throw ArgumentError.value(betrag, 'betrag', 'muss positiv sein');
    _stand += betrag;
  }
 
  @override
  String toString() => '$inhaber: ${_stand.toStringAsFixed(2)}';
}
 
void main() {
  var k = Konto('Mia', 100);
  k.einzahlen(50);
  print(k);
  print('${k.stand} ${Konto.anzahl}');
  var leer = Konto.leer('Tom');
  print(leer);
  try {
    k.einzahlen(-5);
  } on ArgumentError catch (e) {
    print('Fehler: ${e.message}');
  }
  k.stand = 10;
  print(k.stand);
  var kette = StringBuffer()..write('a')..write('b')..write('c');       // Kaskade ..
  print(kette);
}

Ausgabe:

Mia: 150.00
150.0 1
Tom: 0.00
Fehler: muss positiv sein
10.0
abc

Vererbung, abstrakte Klassen, Interfaces

abstract class Tier {
  final String name;
  Tier(this.name);
  String laut();
  String vorstellen() => '$name sagt ${laut()}';
}
 
class Hund extends Tier {
  Hund(super.name);                    // Dart 3: super-Parameter
  @override
  String laut() => 'Wuff';
}
 
class Katze extends Tier {
  int leben = 9;
  Katze(super.name);
  @override
  String laut() => 'Miau';
  @override
  String vorstellen() => '${super.vorstellen()} ($leben Leben)';
}
 
abstract interface class Zahlbar {       // Interface-Klasse
  double betrag();
}
 
class Rechnung implements Zahlbar {
  final double netto;
  Rechnung(this.netto);
  @override
  double betrag() => netto * 1.19;
}
 
void main() {
  List<Tier> tiere = [Hund('Rex'), Katze('Mimi')];
  for (final t in tiere) { print(t.vorstellen()); }
  print(tiere[0] is Hund);
  if (tiere[1] case Katze k) { print('Katze mit ${k.leben} Leben'); }
  Zahlbar z = Rechnung(100);
  print(z.betrag().toStringAsFixed(2));
}

Ausgabe:

Rex sagt Wuff
Mimi sagt Miau (9 Leben)
true
Katze mit 9 Leben
119.00

Mixins, Enums, Extensions

mixin Fliegen {
  String fliegen() => 'fliegt';
}
mixin Schwimmen {
  String schwimmen() => 'schwimmt';
}
class Ente with Fliegen, Schwimmen {}
 
enum Farbe {
  rot('Rot', 0xFF0000),
  gruen('Grün', 0x00FF00),
  blau('Blau', 0x0000FF);
 
  final String anzeige;
  final int hex;
  const Farbe(this.anzeige, this.hex);
  String get code => '#${hex.toRadixString(16).padLeft(6, '0')}';
}
 
extension StringHelfer on String {
  String get umgekehrt => split('').reversed.join();
  bool get istPalindrom => this == umgekehrt;
}
 
extension IntHelfer on int {
  bool get istPrim {
    if (this < 2) return false;
    for (var i = 2; i * i <= this; i++) { if (this % i == 0) return false; }
    return true;
  }
}
 
sealed class Form {}                                   // geschlossene Hierarchie (Dart 3)
class Kreis extends Form { final double r; Kreis(this.r); }
class Quadrat extends Form { final double a; Quadrat(this.a); }
 
double flaeche(Form f) => switch (f) {
  Kreis(r: var r) => 3.14159 * r * r,
  Quadrat(a: var a) => a * a,
};
 
void main() {
  var e = Ente();
  print('${e.fliegen()} und ${e.schwimmen()}');
  print('${Farbe.gruen.anzeige} ${Farbe.gruen.code} ${Farbe.values.length} ${Farbe.rot.name}');
  print('${'Anna'.istPalindrom} ${'Dart'.umgekehrt} ${7.istPrim} ${[for (var i = 1; i < 20; i++) if (i.istPrim) i]}');
  print('${flaeche(Kreis(1)).toStringAsFixed(2)} ${flaeche(Quadrat(3))}');
}

Ausgabe:

fliegt und schwimmt
Grün #00ff00 3 rot
false traD true [2, 3, 5, 7, 11, 13, 17, 19]
3.14 9.0

Generics

class Stapel<T> {
  final List<T> _daten = [];
  void push(T x) => _daten.add(x);
  T? pop() => _daten.isEmpty ? null : _daten.removeLast();
  int get groesse => _daten.length;
  bool get istLeer => _daten.isEmpty;
}
 
T groesstes<T extends Comparable>(List<T> liste) {
  var m = liste.first;
  for (final x in liste) { if (x.compareTo(m) > 0) m = x; }
  return m;
}
 
void main() {
  var s = Stapel<int>();
  s.push(1); s.push(2); s.push(3);
  print('${s.pop()} ${s.pop()} ${s.groesse} ${s.istLeer}');
  print('${groesstes([3, 9, 4])} ${groesstes(['kiwi', 'apfel'])}');
}

Ausgabe:

3 2 1 false
9 kiwi

Merke

  • Klassen mit Konstruktorkurzform Konto(this.name), benannten Konstruktoren, Gettern/Settern; _ macht privat
  • Vererbung extends, abstrakte Klassen, implements für Interfaces, with für Mixins
  • enum mit Feldern, extension für Methoden an bestehenden Typen, sealed für geschlossene Hierarchien
  • Kaskaden .., Generics <T>

Übungsaufgabe

Modelliere Formen als sealed class und berechne ihre Flächen mit einem switch-Ausdruck.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Funktionen, Collections und Records

Weiter: Asynchrone Programmierung, Fehler und Dateien

Alle Kapitel: Dart im Überblick