- •Программирование и алгоритмические языки. Курс за третий семестр. Введение в объектно-ориентированное программирование (ооп)
- •Именование типов в Object Pascal Тип данных «класс»
- •Инкапсуляция
- •Представление данных Данные как функции доступа Свойства
- •Иерархия типов Наследование реализации Проблемы наследования
- •Полиморфизм
- •Проблема множественности иерархий Агрегирование
- •Абстрактные методы и именованные интерфейсы
- •Описание сложного поведения
- •Эволюция пользовательского интерфейса
- •Автоматные модели описания поведения Сложное поведение как изменчивое поведение
- •Программы как символьные преобразования Алфавит как тип данных
- •Программы как синхронные преобразования
- •Тривиальное поведение
- •Нетривиальное поведение
- •Интеллект как рефлексивное, самоопределяемое поведение Машины Тьюринга
- •События как предикаты
- •Событийно управляемое исполнение программ в ооп Программы как тип данных
- •События конечного пользователя и системные, внешние и внутренние
- •Обработка исключений Делегирование
- •Живые данные
- •Задача (проблема) многих тел
- •События как исключения Исключения как события Обработка исключений в Delphi
Иерархия типов Наследование реализации Проблемы наследования
Один модуль использует другой:
interface
implementation
interface
implementation
Наследуем определение функции в первом модуле.
Вопрос: что наследуется?
Может наследоваться имя или interface, то есть это означает, что interface второго модуля более полный, чем первого, то есть это отношение пополнения интерфейса. Наследование интерфейса отражает естественный ход программирования как добавление новых имён. При этом возможны два случая: либо по умолчанию реализация не меняется, либо она меняется, но ссылается на предыдущую. С точки зрения семантики это означает доопределение, или уточнение, значения данного имени. Проще говоря, мы начинаем относиться к функциям и типам как к переменным.
Классический пример: x:=x+1;
Подобное последовательное переопределение значений имён характерно не только для программирования, но и любой классификации.
Животные
Рыбы Млекопитающие Птицы
Акула Карась Дельфин Слон Пингвин Петух
Отметим, что в классической статической интерпретации понятие иерархии формулировалось в терминах пополнения имён. В программировании оно интерпретируется динамически как уточнение преобразований.
Как обычно, в случае древовидных иерархий разделим типы-предки и типы-потомки и определим отношения наследования между типами как пополнение интерфейса и уточнение семантики.
Для создания класса-наследника достаточно указать имя класса предка в его определении:
unit (модуль определения класса-потомка);
uses (модуль определения класса-предка);
interface
(имя класса потомка)=class (имя класса предка)
***********
end;
Любой класс наследуется от единого предка класса tObject (объект вообще).
Пример. Черепашья графика. Простая модель управления роботом-черепашкой, рисующем на дискретной сетке.
unit TurtleGraphicsUnit;
uses GridUnit;
interface
type
private
bPenUp: boolean;{состояние пера}
TurtleGraphicsClass=class(CellGridClass)
public
constructor Create (StartPosition: tPosition);
{Устанавливает начальное состяние сетки и положение черепашки на ней. Тем
самым реализация Create по умолчанию изменяется, перегружается. Методы
предка могут быть переписаны, но не удалены}
constructor Create (Position: tPosition).overload; {Указывает на то, что метод
предка переписан. Остальные
методы добавлены}
procedure PenUp; {поднимаем перо}
procedure PenDown; {опускаем перо}
{Переходим на заданное число шагов. Если перо опущено, оставляем след}
procedure Right(Step: integer);
procedure Left(Step: integer);
procedure Down(Step: integer);
procedure Up(Step: integer);
end;
Итак, у нас появляются два отношения между типами (модуль-класс), отношения использования и отношения наследования. В реализации класса GridUnit сы закрыли опцией private некоторые поля, стремясь скрыть реализацию от пользователя. На деле мы скрыли их от всех остальных модулей, что мешает эффективной реализации нашего класса (TurtleGraphicsUnit). Опция protected закрывает доступ к полям и методам класса для пользователя, но не для наследника.
Перепишем этот класс, в котором методы доступа к полям объявим так: те, что были private, объявим protected. Сами поля оставим private.
implementation
constructor TurtleGraphicsClass.Create(StartPosition: tPosition);
begin
inherited Create; {то есть ссылка на соответствующий метод класса-предка}
set CurrentPosition(StartPosition);
set CurrentColor(cRed);
set CurrentSetColor(cWhite);
end;