The book is currently only available in German.
Klassen-Vervollständigung — `super` und Magic-Methods
Verfügbar — implementiert in Phase B.8. Vollständige Spec in
docs/klassen-erweitert.md.
In Kapitel 22 (B.1) hast du die Klassen-Basis kennengelernt: klasse, Konstruktor neu, dies, Methoden, Vererbung mit erbt. B.8 schließt zwei Lücken: super für Eltern-Aufrufe und vier Magic-Methods, mit denen Klassen sich in eingebaute Operationen einklinken.
32.1 Vorher: Code-Duplikation in Kind-Konstruktoren
klasse Person {
funktion neu(name, alter) {
dies.name = name
dies.alter = alter
}
}
klasse Mitarbeiter erbt Person {
funktion neu(name, alter, firma) {
dies.name = name // ← Duplikation
dies.alter = alter // ← Duplikation
dies.firma = firma
}
}
Wenn Person.neu Validierung oder Default-Werte hinzubekommt, muss Mitarbeiter.neu mitgepflegt werden. Bei drei Vererbungs-Ebenen dreimal.
32.2 Mit super: Eltern-Methode aufrufen
klasse Mitarbeiter erbt Person {
funktion neu(name, alter, firma) {
super.neu(name, alter) // ruft Person.neu mit dem aktuellen dies
dies.firma = firma
}
funktion vorstellen() {
super.vorstellen() // erst Eltern-Logik
sag " ↳ Firma: {dies.firma}"
}
}
super ist ein Pseudo-Receiver, der die gleichnamige Methode der Eltern-Klasse mit demselben dies aufruft. Du kannst ihn nur innerhalb einer Methode verwenden, und nur wenn die Klasse mit erbt eine Eltern-Klasse hat. Sonst gibt's einen klaren Fehler.
32.3 Drei-Ebenen-Vererbung — super macht's stabil
klasse Tier {
funktion ruf() { sag "Tier-Ruf" }
}
klasse Hund erbt Tier {
funktion ruf() {
super.ruf()
sag "Hund-Ruf"
}
}
klasse Welpe erbt Hund {
funktion ruf() {
super.ruf()
sag "Welpe-Ruf"
}
}
(neu Welpe()).ruf()
// Tier-Ruf
// Hund-Ruf
// Welpe-Ruf
Wichtig: super schaut von der Klasse aus, in der die laufende Methode definiert wurde — nicht von der Klasse, von der dies eine Instanz ist. Sonst würde Hund.ruf per super.ruf zu sich selbst springen, weil der Receiver eine Welpe-Instanz ist und Welpe's Eltern Hund ist. Diese Regel macht mehrstufige Vererbung sauber.
32.4 Magic-Method als_text — eigene Display-Form
Klassen rendern standardmäßig als <Klassenname>:
klasse Foo { }
sag (neu Foo()) // <Foo>
Klammern nötig:
sag neu Foo()direkt parst nicht — schreibsag (neu Foo())oder erstnimm f = neu Foo()und dannsag f.
Mit einer als_text-Methode kannst du das überschreiben:
klasse Person {
funktion neu(name, alter) {
dies.name = name
dies.alter = alter
}
funktion als_text() {
gib "Person({dies.name}, {dies.alter})"
}
}
nimm p = neu Person("Sascha", 38)
sag p // Person(Sascha, 38)
sag als_text(p) // Person(Sascha, 38)
sag "Hallo {p}!" // Hallo Person(Sascha, 38)!
Die Methode wird automatisch von sag, als_text(...) und String-Interpolation gerufen. Rückgabe muss text sein — sonst Fehler.
32.5 Magic-Method gleicht — eigene Equality
Standardmäßig sind zwei Instanzen nur gleich, wenn sie dieselbe Reference sind:
klasse P { funktion neu(x) { dies.x = x } }
nimm a = neu P(5)
nimm b = neu P(5)
sag a == b // falsch (Pointer-Equality)
Mit gleicht definierst du Wert-Gleichheit:
klasse Person {
funktion neu(name) { dies.name = name }
funktion gleicht(andere) {
gib typ(andere) == typ(dies) und dies.name == andere.name
}
}
nimm a = neu Person("Anna")
nimm b = neu Person("Anna")
sag a == b // wahr
sag a != b // falsch
inst == nichts ist immer falsch — die gleicht-Methode wird nicht mit nichts gerufen, damit du in deinem Code nicht den nichts-Fall behandeln musst.
Klassen-Vergleich geht auf zwei Wegen, beide funktionieren ab B.8.5:
funktion gleicht(andere) {
gib (typ(andere) == typ(dies) // Workaround-Form, ohne Klassen-Namen
und dies.name == andere.name)
}
// oder direkt mit dem Klassen-Namen:
funktion gleicht(andere) {
gib (typ(andere) == Person // direkt, lesbar (B.8.5+, E-089)
und dies.name == andere.name)
}
Die typ(a) == typ(b)-Form ist nützlich in generischen Methoden, die ohne hartkodierten Klassen-Namen funktionieren sollen (z.B. eine Basis-Klasse, die in der Vererbung von Unterklassen genutzt wird). Die typ(a) == Klasse-Form ist lesbarer wenn die Klasse direkt beim Namen genannt wird. Beide produzieren denselben Wert.
32.6 Magic-Method vergleicht_mit — Sortier-Reihenfolge
Java-Style compareTo. Rückgabe < 0 / 0 / > 0:
klasse Wertung {
funktion neu(p) { dies.p = p }
funktion vergleicht_mit(andere) {
gib dies.p - andere.p
}
}
nimm a = neu Wertung(5)
nimm b = neu Wertung(10)
sag a < b // wahr
sag b > a // wahr
sag a <= a // wahr
Aktiviert <, <=, >, >=. Rückgabe muss ganz/komma/dezimal sein.
Bonus: wenn du vergleicht_mit definierst aber kein gleicht, fällt == automatisch auf vergleicht_mit(andere) == 0 zurück. Wer beides definiert: gleicht gewinnt für ==.
32.7 Magic-Method länge — eigene Length
klasse Sammlung {
funktion neu(items) { dies.items = items }
funktion länge() { gib länge(dies.items) }
}
nimm s = neu Sammlung([1, 2, 3, 4, 5])
sag länge(s) // 5
Rückgabe muss ganz ≥ 0 sein.
32.8 Was Magic-Methods NICHT sind
- Keine speziellen Konstruktoren —
neuist und bleibt der einzige Konstruktor-Name. - Keine versteckten Methoden — du kannst sie ganz normal aufrufen:
inst.als_text()funktioniert. - Keine automatische Generierung — wer keine Magic-Method definiert, bekommt das Default-Verhalten.
32.9 Was kommt nicht in B.8
- Sichtbarkeit
öffentlich/privat— die Tokens sind reserviert, Semantik kommt später. - Statische Methoden (
Foo.fabrik()ohne Instanz) — eigene Phase. - Operator-Overloading für
+,-,*— eigene Phase falls je gewollt. - Subscript-Operator (
inst[i]) — eigene Phase. - Iteration-Protokoll (
wiederhole x in inst) — eigene Phase.
32.10 Praxis: 2D-Punkt mit allem drum-und-dran
klasse Punkt {
funktion neu(x, y) {
dies.x = x
dies.y = y
}
funktion als_text() {
gib "({dies.x}, {dies.y})"
}
funktion gleicht(andere) {
gib (typ(andere) == typ(dies)
und dies.x == andere.x
und dies.y == andere.y)
}
funktion vergleicht_mit(andere) {
// Sortiere primär nach x, sekundär nach y.
wenn dies.x != andere.x {
gib dies.x - andere.x
}
gib dies.y - andere.y
}
funktion verschoben(dx, dy) {
gib neu Punkt(dies.x + dx, dies.y + dy)
}
}
nimm a = neu Punkt(3, 7)
nimm b = a.verschoben(2, 0)
sag "a={a} b={b}" // a=(3, 7) b=(5, 7)
sag a < b // wahr (x=3 < x=5)
sag a == neu Punkt(3, 7) // wahr