Tupel können andere Tupel erweitern. TUPLE: child < parent slots ;
deklariert eine Klasse, deren Instanzen auch Instanzen von parent
sind: Sie erhalten die Slots des Elternteils zusätzlich zu ihren eigenen, und
die Accessoren des Elternteils funktionieren auch für sie, ganz so,
als wären sie direkt im Kind definiert worden.
USING: accessors ;
TUPLE: animal name age ;
TUPLE: dog < animal breed ;
"Rex" 4 "labrador" dog boa .
! => T{ dog { name "Rex" } { age 4 } { breed "labrador" } }
"Rex" 4 "labrador" dog boa name>> . ! => "Rex" (inherited accessor)
boa
Der Konstruktor boa nimmt die Slots in der Reihenfolge ihrer
Deklaration, Eltern zuerst. Für dog oben:
dog boa ( name age breed -- dog )
Ein Enkelkind puppy < dog mit zusätzlichem weeks wäre:
puppy boa ( name age breed weeks -- puppy )
Jede Deklaration mit TUPLE: erzeugt ein Prädikat (name?).
Bei Vererbung verschachteln sich die Prädikate: Jeder Nachkomme
erfüllt die Prädikate seiner Vorfahren:
"Rex" 4 "labrador" dog boa
dup dog? . ! => t
dup animal? . ! => t
Umgekehrt gilt das nicht: Ein animal, das kein dog ist, erfüllt
dog? nicht.
Auch generische Methoden (M:, die in generics
behandelt werden) greifen die Hierarchie hinauf: Eine Methode für animal
wird für jeden Nachkomme ausgeführt, sofern nicht eine spezifischere
Überschreibung Vorrang hat. Das siehst du in boatswains-bilge gleich
nach dieser Übung.
Eine Naturforscherin katalogisiert die Drachen, die rund um die Caldera leben. Sie teilen Merkmale miteinander: Jeder Drache hat einen Namen, eine Farbe und ein Alter. Doch sie sind auf ganz eigene Weise spezialisiert. Du baust einen kleinen Vererbungsbaum aus Drachenklassen und ein einzelnes Wort, das jeden Nachkommen altern lässt.
Definiere den gesamten Vererbungsbaum der Tupelklassen von Anfang an (ihre Konstruktoren kommen in den Aufgaben, die folgen):
dragon mit den Slots name, color und age.fire-dragon, eine Unterklasse von dragon, mit einem zusätzlichen Slot flame-temp.ice-dragon, eine weitere Unterklasse von dragon, mit einem zusätzlichen Slot chill-temp.volcano-dragon, eine Unterklasse von fire-dragon, mit einem zusätzlichen Slot lava-volume.Dann gib dragon einen Konstruktor <dragon>.
"Falkor" "white" 100 <dragon> name>> . ! => "Falkor"
Gib fire-dragon einen Konstruktor <fire-dragon>.
"Smaug" "red" 500 1200 <fire-dragon> flame-temp>> . ! => 1200
"Smaug" "red" 500 1200 <fire-dragon> dragon? . ! => t
Gib ice-dragon einen Konstruktor <ice-dragon>.
"Frosty" "blue" 200 -40 <ice-dragon> chill-temp>> . ! => -40
"Frosty" "blue" 200 -40 <ice-dragon> fire-dragon? . ! => f (siblings)
Gib volcano-dragon einen Konstruktor <volcano-dragon>.
"Vesuvius" "red" 1000 1500 99 <volcano-dragon> dragon? . ! => t
"Vesuvius" "red" 1000 1500 99 <volcano-dragon> fire-dragon? . ! => t
Definiere age-dragon so, dass es den Slot age jedes Drachen (oder Nachkommen) um eins erhöht. Es gibt nichts zurück.
"Falkor" "white" 100 <dragon> dup age-dragon age>> . ! => 101
Dasselbe Wort sollte bei jedem Nachkommen funktionieren. Genau darum geht es bei dem gemeinsamen Zugriffswort.
Melde dich bei Exercism an, um Factor mit 47 Konzepte163 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.