Las tuplas pueden extender otras tuplas. TUPLE: child < parent slots ;
declara una clase cuyas instancias también son instancias de parent:
además de sus propias ranuras tienen las del padre, y los accesores del
padre también funcionan con ellas, como si se hubieran definido en la
clase hija.
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
El constructor boa recibe las ranuras en orden de declaración, primero
los padres. Para el dog de arriba:
dog boa ( name age breed -- dog )
Un nieto puppy < dog que añadiera weeks sería:
puppy boa ( name age breed weeks -- puppy )
Toda declaración TUPLE: genera un predicado (name?).
Con la herencia, los predicados se anidan, de modo que todo descendiente
cumple los predicados de sus antepasados:
"Rex" 4 "labrador" dog boa
dup dog? . ! => t
dup animal? . ! => t
Lo contrario no es cierto: un animal que no es un dog no cumple
dog?.
Los métodos genéricos (M:, que se enseñan en generics)
también despachan por la jerarquía: un método definido en animal se
activa para todos los descendientes, salvo que una sobrescritura más
específica tenga prioridad. Lo verás en boatswains-bilge justo
después de este ejercicio.
Un naturalista está catalogando los dragones que viven alrededor de la caldera. Todos comparten ciertos rasgos (cada dragón tiene un nombre, un color y una edad), pero se especializan de maneras muy diversas. Vas a crear un pequeño árbol de herencia de clases de dragones y un único word que envejece a cualquier descendiente.
Define de antemano todo el árbol de herencia de clases tuple (sus constructores aparecen en las tareas siguientes):
dragon con los slots name, color y age.fire-dragon, una subclase de dragon que añade un slot flame-temp.ice-dragon, otra subclase de dragon que añade un slot
chill-temp.volcano-dragon, una subclase de fire-dragon que añade un
slot lava-volume.A continuación, dale a dragon un constructor <dragon>.
"Falkor" "white" 100 <dragon> name>> . ! => "Falkor"
Dale a fire-dragon un constructor <fire-dragon>.
"Smaug" "red" 500 1200 <fire-dragon> flame-temp>> . ! => 1200
"Smaug" "red" 500 1200 <fire-dragon> dragon? . ! => t
Dale a ice-dragon un constructor <ice-dragon>.
"Frosty" "blue" 200 -40 <ice-dragon> chill-temp>> . ! => -40
"Frosty" "blue" 200 -40 <ice-dragon> fire-dragon? . ! => f (siblings)
Dale a volcano-dragon un constructor <volcano-dragon>.
"Vesuvius" "red" 1000 1500 99 <volcano-dragon> dragon? . ! => t
"Vesuvius" "red" 1000 1500 99 <volcano-dragon> fire-dragon? . ! => t
Define age-dragon para incrementar en uno el slot age de cualquier dragón (o descendiente). No devuelve nada.
"Falkor" "white" 100 <dragon> dup age-dragon age>> . ! => 101
El mismo word debe funcionar en todos los descendientes: eso es precisamente lo que aporta el accesor compartido.
Regístrate en Exercism para aprender y dominar Factor con 47 conceptos163 ejercicios y mentoría humana real, todo gratis.