На этом шаге мы рассмотрим реализацию механизма наследования.
Рассмотрим два класса A и B. Обозначим P(A) множество переменных экземпляра и методов класса A, а P(B) - множество переменных экземпляра и методов класса B. Множества P(A) и P(B) могут находиться в следующих взаимоотношениях:
Если P(A) содержит множество P(B), будем говорить, что класс A является подклассом (Subclass) класса B и соответственно класс B является надклассом (Superclass) класса A. Если же переменные экземпляра и методы совпадают, но тогда мы имеем дело с тем же классом.
Таким образом, у подкласса всегда больше переменных экземпляра и методов, чем у содержащего его надкласса. Его объекты являются в отношении, например, некоторых переменных экземпляра более конкретными (специфичными) по сравнению с объектами надкласса, которые в свою очередь являются более универсальными.
Теперь ясно, что необходим специальный механизм для формирования иерерхической структуры классов. Этой цели служит механизм наследования (Inheritance Mechanism), содержащийся в той или иной форме во всех объектно-ориентированных системах.
Посредством механизма наследования новый определяемый класс может автоматически унаследовать переменные экземпляра и методы класса, определенного как его надкласс. С помощью наследования достигается то, что более общие свойства, связанные с типом более высокого уровня, нет необходимости специально определять в связи с типами нижнего уровня. Достаточно указать, из какого надкласса они наследуются.
Например:
; Определение флэйвера с именем ТЕЛО (DEFFLAVOR ТЕЛО ; Имя флэйвера ( (X 0) (Y 0) (ЦЕНТР-X СОЛНЦЕ-X) ; Свойства (ЦЕНТР-Y СОЛНЦЕ-Y) РАДИУС-ОРБИТЫ ; флэйвера (СЛЕД NIL) (УГОЛ 1) СКОРОСТЬ РАЗМЕР ; ) () ; Надклассы (:SETTABLE-INSTANCE-VARIABLES ЦЕНТР-X ЦЕНТР-Y) ; Режимы )
Планеты и спутники определим как подкласс флэйвера ТЕЛО
(DEFFLAVOR ПЛАНЕТА ; Имя флэйвера ( (СПИСОК-СПУТНИКОВ NIL) ) ; Свойства флэйвера (ТЕЛО) ; Надклассы :SETTABLE-INSTANCE-VARIABLES ; Режимы :GETTABLE-INSTANCE-VARIABLES ) ; ----------------- (DEFFLAVOR СПУТНИК () ; Свойства флэйвера (ТЕЛО) ; Надклассы )
Таким образом, можно упростить определения объектов и сэкономить усилия на их поддержку. Изменения можно локализовать лишь в одном изменяемом месте программы.
В разных системах приняты различные соглашения о том, какова может быть топология структур наследования. Например, в языке Smalltalk у класса может быть только один надкласс, но несколько подклассов. В этом случае возможны лишь структуры наследования в виде дерева.
Система Flavor допускает и циклическое определение, но исключает рекурсивное наследование. Структура определений может быть ориентированным графом, но система распознает циклические определения и обрывает в этом случае наследование. Каждое свойство учитывается лишь один раз.
Учтите, что даже такие многообразные способы наследования могут оказаться ограниченными. Например, в математике и в естественном языке достаточно часто используются рекурсивные типы. Однако для большинства практических применений достаточно ациклических структур. В этом случае класс наследует свойства не только классов, непосредственно стоящих над ним, но и свойства их надклассов, т.е. свойства всех классов, расположенных выше.
Если класс наследует свойства из многих надклассов, то встает вопрос о порядке наследования, когда одноименные свойства наследуются из надклассов, находящихся в различных ветвях, или если один и тот же класс встречается в структуре несколько раз. В каком порядке находятся классы и в каком порядке учитываются свойства?
В принципе возможными последовательностями поиска являются, например, поиск в глубину (Depth First) и по уровням (Level First). В каждой ветви возможными порядками прохождения являются прямой и обратный. Под прямым порядком понимают порядок, в котором узел дерева (или графа) проходится раньше прохождения в том же порядке его поддеревьев. Обратный порядок можно определить аналогично.
В системе Flavor в прохождении иерархии флэйверов применяется поиск в глубину и прямой порядок обхода. Свойства наследуются в том порядке, в котором надклассы указаны в описании класса. Класс с тем же именем повторно не проходится. Предположим, что иерархия классов выглядит так [1, с.114-115]:
Рис.1. Иерархия классов
В этом случае порядок прохода получился бы следующий:
М1 -->М2 -->М4 -->М5 -->М3
Поскольку в разных классах могут быть одноименные, но различные по определениям методы, то для избежания конфликтов нужно договориться о том, какой из них останется в силе. Здесь разумно ограничиться двумя возможностями: в силе остается либо первый метод, либо последний.
В системе Flavor в силе остается первое встретившееся свойство. Если, например, в классе М5 был бы некоторый метод с тем же именем, что и в классе М4, то метод М5 не учитывался бы. Система, однако, дает возможность изменить заложенный по умолчанию порядок следования. Если, например, определяется, что в силе остается последний метод, то говорят, что он перекрывает предыдущие вхождения.
Переменные экземпляра подкласса определяются как множество своих переменных экземпляра и переменных экземпляра надклассов. Если у надкласса некоторого класса есть переменная экземпляра с тем же именем, то она является общей для класса (Shared Instance Variable). Общие переменные можно использовать для связи между классами. Одну и ту же переменную подкласса можно, например, присваивать и читать методами, определенными в разных надклассах.
Кроме определенных пользователем объектов и классов объектная система обычно содержит общие системные классы, свойства которых доступны всем. Такие классы мы назовем базовыми классами.
Например, в системе Flavor есть базовый ванилиновый флэйвер (Vanilla Flavor). Его свойства и методы наследуются автоматически всеми объектами.
Базовый класс может содержать различные системные свойства и действия, такие как:
; Астрономическая модель, представляющая и делающая более ; наглядным строение и функционирование "кусочка" Солнеч- ; ной системы. Модель описывает Солнце и планеты Меркурий, ; Венеру, Землю, Марс и их спутники. (SETQ СОЛНЦЕ-X 150 СОЛНЦЕ-Y 100) (SETQ ДИАМЕТР-СОЛНЦА 10 ОРБИТА-ЗЕМЛИ 149) (SETQ КРАСНЫЙ (+ 2 128)) ;Красный цвет с использованием XOR (SETQ СВЕТЛЫЙ (+ 1 128)) ;Циановый цвет с использованием XOR ; ------------------------------------------------------- (DEFFLAVOR ТЕЛО ; Определение базового класса с именем ТЕЛО ( (X 0) (Y 0) (ЦЕНТР-X СОЛНЦЕ-X) (ЦЕНТР-Y СОЛНЦЕ-Y) РАДИУС-ОРБИТЫ (СЛЕД NIL) (УГОЛ 1) СКОРОСТЬ РАЗМЕР ) () (:SETTABLE-INSTANCE-VARIABLES ЦЕНТР-X ЦЕНТР-Y) ) ; ----------------------------------------- (DEFFLAVOR ПЛАНЕТА ((СПИСОК-СПУТНИКОВ NIL)) ; Планеты определим как подкласс класса ТЕЛО (ТЕЛО) :SETTABLE-INSTANCE-VARIABLES :GETTABLE-INSTANCE-VARIABLES ) ; ------------------- (DEFFLAVOR СПУТНИК () ; Спутники определим как подкласс класса ТЕЛО (ТЕЛО) ) ; ------------------------- (DEFMETHOD (ТЕЛО :ВРАЩАЙСЯ) ; Определение метода :ВРАЩАЙСЯ класса ТЕЛО (ОТНОСИТ-УГОЛ ПЕРЕМЕЩЕНИЕ OldX OldY) (SETQ ОТНОСИТ-УГОЛ СКОРОСТЬ ПЕРЕМЕЩЕНИЕ) (LOOP ( (= ОТНОСИТ-УГОЛ 0) ) (IF (> ОТНОСИТ-УГОЛ 10) (SETQ ОТНОСИТ-УГОЛ (- ОТНОСИТ-УГОЛ 10) ПЕРЕМЕЩЕНИЕ 10) (SETQ ПЕРЕМЕЩЕНИЕ ОТНОСИТ-УГОЛ ОТНОСИТ-УГОЛ 0) ) (SETQ УГОЛ (+ УГОЛ ПЕРЕМЕЩЕНИЕ)) (SETQ OLDX X OLDY Y) (SETQ X (TRUNCATE (+ ЦЕНТР-X (* (SIN-DEG УГОЛ) РАДИУС-ОРБИТЫ)))) (SETQ Y (TRUNCATE (+ ЦЕНТР-Y (* (COS-DEG УГОЛ) РАДИУС-ОРБИТЫ)))) (IF (OR (/= X OLDX) (/= Y OLDY)) (PROG1 (PLOT-CIRCLE OLDX OLDY РАЗМЕР КРАСНЫЙ) ; Стереть окружность (PLOT-CIRCLE X Y РАЗМЕР КРАСНЫЙ) ; Красная окружность (IF СЛЕД (PLOT-DOT X Y СВЕТЛЫЙ) NIL) ) ) ) ) ; ------------------------------------------------------- (DEFMETHOD (ПЛАНЕТА :AFTER :ВРАЩАЙСЯ) (ОЧЕРЕДНОЙ-СПУТНИК) (SETQ S СПИСОК-СПУТНИКОВ) (LOOP ( (NULL S) ) (SETQ ОЧЕРЕДНОЙ-СПУТНИК (POP S)) (SEND ОЧЕРЕДНОЙ-СПУТНИК :SET-ЦЕНТР-X X) (SEND ОЧЕРЕДНОЙ-СПУТНИК :SET-ЦЕНТР-Y Y) (SEND ОЧЕРЕДНОЙ-СПУТНИК :ВРАЩАЙСЯ) ) ) ; ------------------------------------------- ; Тригонометрические функции системы muLISP87 ; ------------------------------------------- (DEFUN SIN-DEG (ANGLE) ; Возвращает значение синуса аргумента, ; выраженного в градусах ( (MINUSP ANGLE) (SETQ ANGLE (DIVIDE (REM (- ANGLE) 360) 45)) (- (SIN-COS-DEG (CAR ANGLE) (CDR ANGLE))) ) (SETQ ANGLE (DIVIDE (REM ANGLE 360) 45)) (SIN-COS-DEG (CAR ANGLE) (CDR ANGLE)) ) ; -------------------- (DEFUN COS-DEG (ANGLE) ; Возвращает значение косинуса аргумента, ; выраженного в градусах (SETQ ANGLE (DIVIDE (REM (ABS ANGLE) 360) 45)) (SIN-COS-DEG (+ 2 (CAR ANGLE)) (CDR ANGLE)) ) ; ------------------------------- (DEFUN SIN-COS-DEG (N45DEG RESID) ((> N45DEG 3) (- (SIN-COS-DEG (- N45DEG 4) RESID)) ) ( (ZEROP N45DEG) (REDUCED-SIN RESID) ) ( (EQ N45DEG 1) ( (ZEROP RESID) 0.70710678 ) (REDUCED-COS (- 45 RESID))) ( (EQ N45DEG 2) (REDUCED-COS RESID) ) ( (ZEROP RESID) 0.70710678 ) (REDUCED-SIN (- 45 RESID)) ) ; ---------------------- (DEFUN REDUCED-SIN (DEG) (/ (* DEG (+ 1324959969 (* (SETQ DEG (* DEG DEG)) (+ -67245 DEG)))) 75914915920) ) ; ---------------------- (DEFUN REDUCED-COS (DEG) (SETQ DEG (* DEG DEG)) (/ (+ 266153374 (* DEG (+ -40518 DEG))) 266153374) ) ; ------------------------- (DEFUN SOLAR () ; Основная функция (SETQ МАРС (MAKE-INSTANCE ПЛАНЕТА :РАДИУС-ОРБИТЫ 114 :СКОРОСТЬ 0.053 :РАЗМЕР 4) ) (SETQ ФОБОС (MAKE-INSTANCE СПУТНИК :ЦЕНТР-X 48 :ЦЕНТР-Y 48 :РАДИУС-ОРБИТЫ 7 :СКОРОСТЬ 114.4 :РАЗМЕР 3) ) (SETQ МЕРКУРИЙ (MAKE-INSTANCE ПЛАНЕТА :РАДИУС-ОРБИТЫ 29 :СКОРОСТЬ 0.416 :РАЗМЕР 3) ) (SETQ ВЕНЕРА (MAKE-INSTANCE ПЛАНЕТА :РАДИУС-ОРБИТЫ 54 :СКОРОСТЬ 0.416 :РАЗМЕР 5) ) (SETQ ЗЕМЛЯ (MAKE-INSTANCE ПЛАНЕТА :РАДИУС-ОРБИТЫ 84 :СКОРОСТЬ 0.1 :РАЗМЕР 6) ) (SETQ ЛУНА (MAKE-INSTANCE СПУТНИК :ЦЕНТР-X 48 :ЦЕНТР-Y 48 :РАДИУС-ОРБИТЫ 15 :СЛЕД T :СКОРОСТЬ 1.3 :РАЗМЕР 3) ) (SETQ ДЕЙМОС (MAKE-INSTANCE СПУТНИК :ЦЕНТР-X 48 ;(SEND МАРС :X) :ЦЕНТР-Y 48 ;(SEND МАРС :Y) :РАДИУС-ОРБИТЫ 12 :СКОРОСТЬ 30.4 :РАЗМЕР 3) ) ; "Присваивание" спутников Земле и Марсу (SEND ЗЕМЛЯ :SET-СПИСОК-СПУТНИКОВ (LIST ЛУНА)) (SEND МАРС :SET-СПИСОК-СПУТНИКОВ (LIST ФОБОС ДЕЙМОС)) ; Запуск Солнечной системы (VIDEO-MODE 4) (PLOT-CIRCLE СОЛНЦЕ-X СОЛНЦЕ-Y (- ДИАМЕТР-СОЛНЦА 3) КРАСНЫЙ) (LOOP (PLOT-CIRCLE СОЛНЦЕ-X СОЛНЦЕ-Y (- ДИАМЕТР-СОЛНЦА 3) КРАСНЫЙ) (PLOT-CIRCLE СОЛНЦЕ-X СОЛНЦЕ-Y (- ДИАМЕТР-СОЛНЦА 1) КРАСНЫЙ) (PLOT-CIRCLE СОЛНЦЕ-X СОЛНЦЕ-Y ДИАМЕТР-СОЛНЦА КРАСНЫЙ) ; Пусть вращаются планеты! (SEND МЕРКУРИЙ :ВРАЩАЙСЯ) (SEND ВЕНЕРА :ВРАЩАЙСЯ) (SEND ЗЕМЛЯ :ВРАЩАЙСЯ) (SEND МАРС :ВРАЩАЙСЯ) ) ) (SOLAR)
l.com flavors.lsp
(LOAD L112_1.LSP)
Кроме того, можно выделить абстрактные совокупности свойств в характеристические классы и использовать их в определениях. Характеристический класс может содержать свойства, противоположные или аналогичные свойствам базовых классов в их естественной классификации.
Например, классы "солнце" и "яблоко" могли бы унаследовать из некоторого класса геометрических свойств свойство "круглый".
Наиболее важное преимущество объектного программирования, пожалуй, и состоит в том, что оно предлагает механизм абстракции для разбиения задачи и ее решения на части. С другой стороны, оно предполагает, что объекты проблемной области, а также их свойства и зависимости должны быть тщательно проанализированы.
Чтобы различить классы, можно использовать естественное разбиение объектов на разные классы. Например, живые существа разделяются на млекопитающих, птиц, пресмыкающихся, рыб, насекомых и т.д. Далее они подразделяются на подклассы в соответствии с дополнительными свойствами каждого вида.
Со следующего шага мы приведем задания для самостоятельного решения.