Le tuple possono estendere altre tuple. TUPLE: child < parent slots ;
dichiara una classe le cui istanze sono anche istanze di parent:
ricevono gli slot del genitore in aggiunta ai propri, e anche gli
accessor del genitore funzionano su di esse, esattamente come se fossero
stati definiti sulla classe figlia.
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
Il costruttore boa prende gli slot nell'ordine di dichiarazione, prima
i genitori. Per dog qui sopra:
dog boa ( name age breed -- dog )
Un nipote puppy < dog che aggiunge weeks sarebbe:
puppy boa ( name age breed weeks -- puppy )
Ogni dichiarazione TUPLE: genera un predicato (name?).
Con l'ereditarietà i predicati si annidano: ogni discendente
soddisfa i predicati dei suoi antenati:
"Rex" 4 "labrador" dog boa
dup dog? . ! => t
dup animal? . ! => t
Il contrario non è vero: un animal che non è un dog non
supera dog?.
Anche i metodi generici (M:, insegnati in generics)
fanno dispatch lungo la gerarchia: un metodo su animal scatta per
ogni discendente, a meno che un override più specifico abbia la
priorità. Lo vedrai in boatswains-bilge subito dopo questo esercizio.
Un naturalista sta catalogando i draghi che vivono intorno alla caldera. Condividono alcune caratteristiche (ogni drago ha un nome, un colore e un'età), ma si specializzano in modi tutti loro. Costruirai un piccolo albero di ereditarietà di classi di draghi e una singola parola che fa invecchiare qualsiasi discendente.
Definisci in anticipo l'intero albero di ereditarietà delle classi tuple (i loro costruttori arriveranno nelle attività che seguono):
dragon con gli slot name, color, age.fire-dragon, una sottoclasse di dragon, che aggiunge uno slot flame-temp.ice-dragon, un'altra sottoclasse di dragon, che aggiunge uno slot chill-temp.volcano-dragon, una sottoclasse di fire-dragon, che aggiunge uno slot lava-volume.Poi assegna a dragon un costruttore <dragon>.
"Falkor" "white" 100 <dragon> name>> . ! => "Falkor"
Assegna a fire-dragon un costruttore <fire-dragon>.
"Smaug" "red" 500 1200 <fire-dragon> flame-temp>> . ! => 1200
"Smaug" "red" 500 1200 <fire-dragon> dragon? . ! => t
Assegna a ice-dragon un costruttore <ice-dragon>.
"Frosty" "blue" 200 -40 <ice-dragon> chill-temp>> . ! => -40
"Frosty" "blue" 200 -40 <ice-dragon> fire-dragon? . ! => f (siblings)
Assegna a volcano-dragon un costruttore <volcano-dragon>.
"Vesuvius" "red" 1000 1500 99 <volcano-dragon> dragon? . ! => t
"Vesuvius" "red" 1000 1500 99 <volcano-dragon> fire-dragon? . ! => t
Definisci age-dragon per incrementare di uno lo slot age di qualsiasi drago (o discendente). Non restituisce nulla.
"Falkor" "white" 100 <dragon> dup age-dragon age>> . ! => 101
La stessa parola dovrebbe funzionare su ogni discendente: è proprio questo il senso della parola di accesso condivisa.
Iscriviti a Exercism per imparare e padroneggiare Factor con 47 concetti163 esercizi e il mentoring di persone reali, tutto gratis.