- •Введение
- •Как использовать руководства по Borland Pascal
- •Глава 1. Установка и запуск Borland Pascal
- •Использование программы Install
- •Программа Install и Windows
- •Запуск Borland Pascal
- •Защищенный режим и память
- •Запуск Borland Pascal for Windows
- •Запуск bp.Exe в расширенном режиме Windows 386
- •Запуск bp.Exe в стандартном режиме Windows
- •Запуск bp.Exe в окне Windows dos
- •Жидкокристаллические и плазменные экраны
- •Файл readme
- •Файлы filelist.Doc и helpme!.Doc
- •Примеры программ
- •Глава 2. Что нового в Borland Pascal
- •Три интегрированных интерактивных среды разработки программ
- •Новые средства ide
- •Компилятор командной строки, работающий в защищенном режиме
- •Среда разработки программ защищенного режима dos
- •Динамически компонуемые библиотеки dos
- •Добавления к языку Паскаль
- •Улучшения в библиотеке исполняющей системы
- •Новые подпрограммы модуля System
- •Новые модули
- •Новые директивы компилятора
- •Усовершенствования компилятора
- •Улучшения в Turbo Vision
- •Улучшения ObjectWindows
- •Новые средства и утилиты
- •Глава 3. Основы интегрированной среды для dos
- •Запуск ide
- •Компоненты интегрированной среды
- •Окна ide
- •Управление окном
- •Строка состояния
- •Диалоговые окна
- •Глава 4. Программирование в интегрированной интерактивной среде для dos
- •Запуск ide и выход из нее
- •Параметры запуска
- •Установка параметров запуска в интегрированной среде
- •Выход из ide
- •Использование справочной системы Help
- •Перемещение в справочной системе
- •Запрос помощи
- •Копирование примеров исходного кода
- •Загрузка других справочных файлов
- •Выход из справочника Help
- •Запись и редактирование исходного кода
- •Настройка конфигурации редактора
- •Изменение решения: команда Undo
- •Групповая отмена
- •Отмена отмены
- •Работа с блоками текста
- •Выделение блока
- •Вырезание, копирование и вставка блоков
- •Изменение поведения выделенных блоков
- •Поиск и замена
- •Соответствие пар ограничителей
- •Переход к строке с заданным номером
- •Использование локального меню окна редактирования
- •Выделение синтаксиса
- •Выбор файлов для выделения
- •Запрещение выделения синтаксиса
- •Глава 4. Программирование в интегрированной интерактивной среде для dos (часть2) Печать исходного кода
- •Работа с файлами
- •Открытие файлов
- •Открытие файла в позиции курсора
- •Компиляция и выполнение
- •Выбор целевой платформы
- •Компиляция
- •Формирование (Make)
- •Построение (Build)
- •Выполнение
- •Передача программе параметров
- •Параметры компилятора и компоновщика
- •Оптимизация кода
- •Условная компиляция
- •Директивы define и undef
- •Предопределенные идентификаторы
- •Идентификаторы iFxxx, else и endif
- •Директивы ifdef и ifndef
- •Директива ifopt
- •Просмотр исходного кода
- •Просмотр объектов
- •Просмотр модулей
- •Просмотр глобальных идентификаторов
- •Просмотр идентификаторов в исходном коде
- •Просмотр функций ObjectBrowser
- •Выполнение в ide других программ
- •Настройка меню Tools
- •Работа с окном Messages
- •Настройка конфигурации ide
- •Сохранение рабочей операционной среды
- •Использование файла конфигурации
- •Использование файла оперативной области
- •Управление проектом
- •Глава 5. Программирование в интегрированной интерактивной среде для Windows
- •Запуск ide для Windows
- •Использование оперативной полосы
- •Настройка конфигурации оперативной полосы
- •Использование справочной системы Help
- •Перемещение по справочной системе
- •Запрос помощи
- •Копирование примеров кода
- •Выход из справочной системы
- •Запись и редактирование исходного кода
- •Настройка конфигурации редактора
- •Набор команд
- •Использование редактора
- •Выделение синтаксиса
- •Цветовое выделение текста
- •Использование системных цветов Windows
- •Изменение атрибутов текста
- •Печать исходного кода
- •Работа с файлами
- •Открытие файлов
- •Где находятся файлы?
- •Работа с файлами в другом каталоге
- •Компиляция и выполнение
- •Просмотр исходного кода
- •Просмотр объектов
- •Буквенные символы в ObjectBrowser
- •Фильтры
- •Просмотр глобальных идентификаторов
- •Просмотр идентификаторов в исходном коде
- •Выполнение в ide других программ
- •Настройка конфигурации ide
- •Глава 6. Отладка в интегрированной среде
- •Что такое отладка?
- •Какие существуют виды ошибок?
- •Методы отладки
- •Генерация отладочной информации
- •Управление выполнением
- •Что такое шаг?
- •Выполнение программы по шагам
- •Трассировка программы
- •Трассировка или выполнение по шагам?
- •Выполнение больших фрагментов
- •Поиск нужного места
- •Повторное выполнение
- •Отслеживание вывода программы
- •Переключение экранов
- •Окно Output
- •Использование двух мониторов
- •Просмотр значений
- •Что такое выражение?
- •Просмотр выражений
- •Спецификаторы формата в выражениях отладчика
- •Вычисление и модификация
- •Использование точек останова
- •Задание точек останова
- •Отмена точке останова
- •Модификация точек останова
- •Создание условный точек останова
- •Прерывание программы без точек останова
- •Глава 7. Модули Borland Pascal
- •Что такое модуль?
- •Структура модуля
- •Интерфейсная секция
- •Секция реализации
- •Секция инициализации
- •Как используются модули?
- •Ссылки на описания модуля
- •Оператор uses секции реализации
- •Стандартные модули
- •Создание ваших собственных модулей
- •Компиляция модуля
- •Доступность модуля для программы
- •Модули и большие программы
- •Утилита tpumover
- •Глава 7. Модули Borland Pascal
- •Что такое модуль?
- •Структура модуля
- •Интерфейсная секция
- •Секция реализации
- •Секция инициализации
- •Как используются модули?
- •Ссылки на описания модуля
- •Оператор uses секции реализации
- •Стандартные модули
- •Создание ваших собственных модулей
- •Компиляция модуля
- •Доступность модуля для программы
- •Модули и большие программы
- •Утилита tpumover
- •Глава 9. Объектно-ориентированное программирование
- •Объекты
- •Наследование
- •Объекты: наследующие записи
- •Экземпляры объектных типов
- •Поля объектов
- •Хорошая и плохая техника программирования
- •Совмещенные код и данные
- •Определение методов
- •Область действия метода и параметр Self
- •Поля данных объекта и формальные параметры метода
- •Объекты, экспортируемые модулями
- •Секция private
- •Программирование в "действительном залоге"
- •Глава 9. Объектно-ориентированное программирование(часть2) Инкапсуляция
- •Методы: никакого ухудшения
- •Расширяющиеся объекты
- •Наследование статических методов
- •Виртуальные методы и полиморфизм
- •Раннее связывание против позднего связывания
- •Совместимость типов объектов
- •Полиморфические объекты
- •Виртуальные методы
- •Проверка диапазонов при вызове виртуальных методов
- •Расширяемость объекта
- •Статические методы или виртуальные методы?
- •Динамические объекты
- •Размещение и инициализация с помощью процедуры New
- •Удаление динамических объектов
- •Деструкторы
- •Пример размещения динамического объекта
- •Что же дальше?
- •Заключение
- •Глава 10. Взгляд на Windows
- •Что такое приложение Windows?
- •Преимущества Windows
- •Требования
- •Программные средства
- •Архитектура с управлением по событиям
- •Графика, независимая от устройств
- •Многозадачность
- •Управление памятью
- •Ресурсы
- •Динамическая компоновка
- •Буфер вырезанного изображения
- •Динамический обмен данными
- •Множественный документальный интерфейс
- •Типы данных Windows
- •Объектно-ориентированная работа с окнами
- •Лучший интерфейс с Windows
- •Интерфейсные объекты
- •Абстрагирование функций Windows
- •Автоматизация ответа на сообщения
- •Структура программы Windows
- •Структура Windows
- •Взаимодействие с Windows и dos
- •Элементарная программа
- •Действия программы при запуске
- •Назначение основного окна
- •Цикл разработки прикладной программы
- •Изучение ObjectWindows
Наследование статических методов
Все показанные до сих пор методы, связанные с типами объек-
тов TEmployee, THourly, TSalaried и TCommissioned, являются ста-
тическими методами. Однако, со статическими методами связана
пpоблема наследования.
Для того, чтобы разобраться с этой проблемой, отложим в сто-
рону наш пример с платежной ведомостью и рассмотрим другой упро-
щенный и нереалистичный, но показательный пример. Вернемся к кры-
латым насекомым. Предположим, что нужно создать программу, кото-
рая будет рисовать на экране различные типы летающих насекомых.
Предположим, вы решили, что на вершине иерархии будет находиться
объект Winged. Пусть вы планируете, что новые типы объектов лета-
ющих насекомых как будут строиться как потомки Winged. Например,
вы можете создать тип объекта Bee, который отличается от родс-
твенных крылатых насекомых тем, что имеет жало и полосы. Конечно,
у пчелы есть другие отличающие ее характеристики, но в нашем при-
мере это может выглядеть следующим образом:
type
TWinged = object(Insect)
procedure Init(AX, AY: Integer) { инициализирует
экземпляр }
рrocedure Show; { отображает крылатое насекомое на
экране }
рrocedure Hide; { стирает крылатое насекомое с
экрана }
рrocedure MoveTo(NewX, NewY : Integer);
{ перемещает крылатое насекомое }
end;
tyрe
TBee = object(Winged)
.
.
.
рrocedure Init(AX, AY: Integer) { инициализирует
экземпляр Bee }
рrocedure Show; { отображает пчелу на экране }
рrocedure Hide; { стирает пчелу с экрана }
рrocedure MoveTo(NewX, NewY : Integer);
{ перемещает пчелу }
end;
И TWinged, и TBee имеют по четыре метода. TWinged.Init и
TBee.Init инициализируют экземпляр соответствующих объектов. Ме-
тод TWinged.Show знает, как рисовать крылатое насекомое на
экране, а метод TBee.Show - как рисовать пчелу (крылатое насеко-
мое с полосками на теле и с жалом). Метод TWinged.Hide знает, как
стирать крылатое насекомое с экрана, а метод TBee.Hide - как
стирать пчелу. Два метода Show отличаются друг от друга, равно
как и два метода Hide.
Однако, методы TWinged.MoveTo и TBee.MoveTo полностью одина-
ковы. В нашем примере X и Y определяют положение на экране.
рrocedure TWinged.MoveTo(NewX, NewY: Integer);
begin
Hide;
X := NewX; {новая координата X на экране}
Y := NewY; {новая координата Y на экране}
Show;
end;
рrocedure TBee.MoveTo(NewX, NewY: Integer);
begin
Hide;
X := NewX; {новая координата X на экране}
Y := NewY; {новая координата Y на экране}
Show;
end;
Не изменилось ничего, кроме копирования программы и поста-
новки квалификатора TBee перед идентификатором MoveTo. Так как
методы одинаковы, зачем нужно помещать MoveTo в TBee? Ведь Bee
автоматически наследует MoveTo от TWinged. Поэтому не нужно
переопределять метод MoveTo из TWinged, но это именно то место,
где возникает проблема в случае статических методов.
Термин "статический" был выбран для описания методов, не яв-
ляющихся виртуальными - термин, который мы введем далее. Факти-
чески, виртуальные методы являются решением этой проблемы, но
прежде чем понять решение, вам следует разобраться в самой проб-
леме.
Признаки проблемы состоят в следующем: пока копия метода
MoveTo не будет помещена в область действия TBee для подавления
метода MoveTo объекта TWinged, метод не будет работать правильно,
если он будет вызываться из объекта типа TBee. Если TBee запуска-
ет метод MoveTo объекта TWinged, так то, что движется по экрану,
является крылатым насекомым, а не пчелой. Только когда TBee вызы-
вает копию метода MoveTo, определенного в его собственной области
действия, на экране с помощью вызовов Show и Hide будут рисовать-
ся и стираться пчелы.
Почему это так? Это объясняется способом, которым компилятор
разрешает вызовы методов. Когда компилируются методы Bee, то сна-
чала встречаются TWinged.Show и TWinged.Hide и их код компилиру-
ется в сегмент кода. Немного позднее в файле встречается метод
Winged.MoveTo, который вызывает TWinged.Show и TWinged.Hide. Как
и при вызове любой процедуры, компилятор замещает ссылки на
TWinged.Show и TWinged.Hide в исходном коде на их адреса, сгене-
рированные в сегменте кода. Таким образом, когда вызывается код
TWinged.MoveTo, он, в свою очередь, вызывает TWinged.Show и
TWinged.Hide со всеми вытекающими последствиями.
До сих пор это был типичный для Borland Pascal сценарий и он
был бы справедлив (за исключением номенклатуры), начиная с версии
1.0 Turbo Pascal 1983 года. Однако, дело меняется, когда вы вклю-
чаете в этот сценарий принцип наследования. Когда TBee наследует
метод от TWinged, он (TBee) использует метод в точности так, как
тот был откомпилирован.
Снова посмотрите, что должен наследовать TBee, если он нас-
ледует TWinged.MoveTo:
рrocedure TWinged.MoveTo(NewX, NewY: integer);
begin
Hide; { Вызов Winged.Hide }
X := NewX;
Y := NewY;
Show { Вызов Winged.Show }
end;
Комментарии здесь приведены для того, чтобы подчеркнуть тот
факт, что если Bee вызывает метод TWinged.MoveTo, то он также вы-
зывает TWinged.Show и TWinged.Hide, а не TBee.Show и TBee.Hide.
Поскольку TWinged.MoveTo вызывает методы TWinged.Show и
TWinged.Hide, TWinged.MoveTo нельзя наследовать. Вместо этого, он
должен быть переопределен своей второй копией, которая вызывает
копии Show и Hide, определенные внутри области действия второй
копии, то есть, TBee.Show и TBee.Hide.
При разрешении вызовов методов, логика компилятора работает
так: при вызове метода компилятор сначала ищет метод, имя которо-
го определено внутри типа объекта. Тип TBee определяет методы с
именами Init, Hide, Show и MoveTo. Если метод TBee должен был
вызвать один из этих четырех методов, то компилятор заменил бы
вызов на адрес одного из собственных методов Bee.
Если в типе объекта не определен метод с таким именем, то
компилятор поднимается выше к непосредственному родительскому ти-
пу в поисках метода с указанным именем. Если метод с таким именем
найден, то адрес родительского метода замещает имя в исходном ко-
де дочернего метода. Если метод с таким именем не найден, то ком-
пилятор продолжает продвигаться вверх по родительским объектам в
поисках метода. Если компилятор наталкивается на самый первый
(высший) тип объекта, то он выдает сообщение об ошибке, указываю-
щее, что ни одного такого метода не определено.
Однако, если статический наследуемый метод найден и исполь-
зуется, то вы должны помнить, что вызываемый метод является в
точности таким, как он определен и компилирован для родительского
типа. Если родительский метод вызывает другие методы, то вызывае-
мые методы будут также родительскими методами, даже если дочерний
объект содержит методы, которые переопределяют родительские.