As tuplas podem estender outras tuplas. TUPLE: child < parent slots ;
declara uma classe cujas instâncias também são instâncias de parent:
recebem as fendas do parent para além das suas, e os acessores do parent
também funcionam nelas, tal como se tivessem sido definidos na child.
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
O construtor boa recebe as fendas pela ordem de declaração, começando
pelo parent. Para o dog acima:
dog boa ( name age breed -- dog )
Uma classe neta puppy < dog que acrescente weeks seria:
puppy boa ( name age breed weeks -- puppy )
Cada declaração TUPLE: gera um predicado (name?).
Com herança, os predicados aninham-se: cada descendente
satisfaz os predicados dos seus ascendentes:
"Rex" 4 "labrador" dog boa
dup dog? . ! => t
dup animal? . ! => t
O contrário não é verdade: um animal que não seja um dog não passa
no dog?.
Os métodos genéricos (M:, ensinados em generics)
também se resolvem pela hierarquia acima: um método definido em animal
é executado para todos os descendentes, a menos que uma sobreposição
mais específica tenha prioridade. Vais ver isso em boatswains-bilge
logo a seguir a este exercício.
Um naturalista está a catalogar os dragões que vivem à volta da caldeira. Todos partilham características entre si, ou seja, cada dragão tem um nome, uma cor e uma idade, mas especializam-se de formas muito próprias. Vais construir uma pequena árvore de herança de classes de dragões e uma única palavra que envelhece qualquer descendente.
Define desde logo toda a árvore de herança de classes de tuplos (os respetivos construtores vêm nas tarefas seguintes):
dragon, com os slots name, color e age.fire-dragon, uma subclasse de dragon, com um slot adicional flame-temp.ice-dragon, outra subclasse de dragon, com um slot adicional chill-temp.volcano-dragon, uma subclasse de fire-dragon, com um slot adicional
lava-volume.Depois, dá a dragon um construtor <dragon>.
"Falkor" "white" 100 <dragon> name>> . ! => "Falkor"
Dá a fire-dragon um construtor <fire-dragon>.
"Smaug" "red" 500 1200 <fire-dragon> flame-temp>> . ! => 1200
"Smaug" "red" 500 1200 <fire-dragon> dragon? . ! => t
Dá a ice-dragon um construtor <ice-dragon>.
"Frosty" "blue" 200 -40 <ice-dragon> chill-temp>> . ! => -40
"Frosty" "blue" 200 -40 <ice-dragon> fire-dragon? . ! => f (siblings)
Dá a volcano-dragon um construtor <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 em uma unidade o slot age de qualquer dragão (ou
descendente). Não devolve nada.
"Falkor" "white" 100 <dragon> dup age-dragon age>> . ! => 101
A mesma palavra deve funcionar em todos os descendentes: é precisamente esse o objetivo do acessor partilhado.
Inscreve-te no Exercism para aprenderes e dominares Factor com 47 conceitos163 exercícios, e mentoria humana real, tudo grátis.