元組可以擴充其他元組。TUPLE: child < parent slots ;會宣告一個類別,它的實例同時也是parent的實例:它們除了自己的槽位之外,還會一併取得父類別的槽位,而父類別的存取子在它們身上也同樣有效,就好像那些存取子原本就定義在子類別上一樣。
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的槽位順序boa建構子接受槽位的順序是宣告順序,父類別優先。對上面的dog來說:
dog boa ( name age breed -- dog )
一個加上weeks的孫類別puppy < dog 則會是:
puppy boa ( name age breed weeks -- puppy )
每個TUPLE:宣告都會產生一個述詞(name?)。
有了繼承之後,這些述詞會形成巢狀,每個後代都滿足祖先的述詞:
"Rex" 4 "labrador" dog boa
dup dog? . ! => t
dup animal? . ! => t
反過來並不成立:不是dog的animal無法通過dog?。
泛型方法(M:,會在generics中介紹)也會沿著階層往上分派:定義在animal上的方法會對每個後代生效,除非有更具體的覆寫取得優先權。你在緊接著這個練習之後的boatswains-bilge裡馬上就會看到。
一位博物學家正在為住在破火山口周圍的龍建立目錄。牠們彼此共享一些特徵,每條龍都有名字、顏色和年齡,但各自又有獨特的專精之處。你會建立一棵小小的龍類別繼承樹,還要寫出一個能讓任何後代變老的詞。
先一口氣定義好整棵元組類別的繼承樹(它們的建構子會在後續的任務中介紹):
dragon,帶有 name、color、age三個槽位。fire-dragon,dragon的子類別,新增一個 flame-temp槽位。ice-dragon,dragon的另一個子類別,新增一個 chill-temp槽位。volcano-dragon,fire-dragon的子類別,新增一個 lava-volume槽位。接著幫 dragon定義一個 <dragon>建構子。
"Falkor" "white" 100 <dragon> name>> . ! => "Falkor"
幫 fire-dragon定義一個 <fire-dragon>建構子。
"Smaug" "red" 500 1200 <fire-dragon> flame-temp>> . ! => 1200
"Smaug" "red" 500 1200 <fire-dragon> dragon? . ! => t
幫 ice-dragon定義一個 <ice-dragon>建構子。
"Frosty" "blue" 200 -40 <ice-dragon> chill-temp>> . ! => -40
"Frosty" "blue" 200 -40 <ice-dragon> fire-dragon? . ! => f (siblings)
幫 volcano-dragon定義一個 <volcano-dragon>建構子。
"Vesuvius" "red" 1000 1500 99 <volcano-dragon> dragon? . ! => t
"Vesuvius" "red" 1000 1500 99 <volcano-dragon> fire-dragon? . ! => t
定義 age-dragon,把任何龍(或後代)的 age 槽位加一。它不會回傳任何東西。
"Falkor" "white" 100 <dragon> dup age-dragon age>> . ! => 101
同一個詞應該能用在每一個後代身上,這正是共用存取器的意義所在。