元组可以扩展其他元组。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
同一个词应当对每个后代都有效,这正是共享访问器的意义所在。