Кортежі можуть розширювати інші кортежі. 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 )
Онук puppy < dog , що додає weeks, матиме такий вигляд:
puppy boa ( name age breed weeks -- puppy )
Кожне оголошення TUPLE: породжує предикат (name?).
З успадкуванням предикати вкладаються одне в одне: кожен нащадок
задовольняє предикати своїх предків:
"Rex" 4 "labrador" dog boa
dup dog? . ! => t
dup animal? . ! => t
Зворотне неправильне: animal, який не є dog, не задовольняє
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
Те саме слово має працювати для кожного нащадка: у цьому й полягає сенс спільного аксесора.
Зареєструйтеся на Exercism, щоб вивчати й опановувати Factor, а також 47 концепцій163 вправи та справжнє наставництво від людей, і все це безкоштовно.