- •Объектно-ориентированное программирование
- •Часть 1 классы и объекты
- •Введение
- •1. Классы и объекты
- •Var aLine: tLine;
- •Var aColorLine: tColorLine;
- •2. Методы
- •2.1. Методы-функции и методы-процедуры
- •2.2. Конструкторы и деструкторы
- •Inherited Create;
- •Var TmpFrm: tForm;
- •Var Mem: tMemo;
- •2.3. Классовые процедуры и функции
- •Var s: String;
- •2.4. Скрытый Self
- •3. Видимость компонентов класса
- •4. Наследование
- •4.1. Основные понятия
- •4.2. Наследование полей
- •4.3. Поведение методов при наследовании
- •Var SomeObject: t1;
- •Virtual;
- •Virtual; Abstract;
- •4.4. Иерархия классов
- •4.5. Rtti
- •4.6. Проверка типа
- •4.7. Приведение типа
- •4.8. Указатели на класс
- •Var ObjRef: tObjRef;
- •Implementation
- •X, y, w, h: Integer): tControl;
- •5. Полиморфизм
- •6. Свойства (properties)
- •6.1. Объявление свойств
- •6.2. Объявления свойств-массивов
- •Var I: Byte;
- •6.3. Раздел Read
- •6.4. Раздел Write
- •Inherited Create;
- •Inherited Destroy;
- •6.5. Команды Default, NoDefault и Stored
- •6.6. Команда Index
- •Var aYear, aMonth, aDay: Word;
- •Var aYear, aMonth, aDay: Word;
- •6.7. Команды DispId и Implements
- •6.8. Переопределение свойств при наследовании
- •7. События (events)
- •7.1. Объявление событий
- •IfAssigned(fOnMouseMove) Then fOnMouseMove(Self, Shift, X, y);
- •Vk_return: NumMemo.DoNumStr(l);
- •Vk_return: PostMessage(NumMemo.Handle, wm_user1,1, 0);
- •7.2. Обработчики событий
- •7.3. Делегирование событий
- •Var Objl: tIstClass;
- •7.4. Переопределение стандартных событий
- •Var NewBtn: tNewButton;
Virtual; Abstract;
Procedure <имя метода>[(<параметры>)]; Dynamic; Abstract;
Function <имя метода>[(<параметры>)]: <тип результата>;
Dynamic; Abstract;
В VMT (DMT) для абстрактного метода резервируется строка, в которую вместо адреса вызова метода заносится Nil.
В общем контексте под виртуальными методами понимают как собственно виртуальные методы, так и динамические методы или Override-методы (замещаемые).
Таким образом, у каждого классового типа имеется своя уникальная VMT. Блок данных экземпляра класса, в свою очередь, содержит скрытый указатель на VMT своего классового типа. Когда транслятору необходимо сгенерировать код для вызова виртуального метода, он сначала генерирует код для получения указателя на VMT из данных экземпляра класса (первого поля), затем получает адрес кода нужного метода из соответствующего поля VMT, после чего выполняет вызов по полученному адресу. Реально на все это требуется две машинные инструкции.
Примечание:
• Объявления методов, как и полей можно переносить из одного раздела в другой. Невозможно только переносить объявления из раздела Private в раздел с большей видимостью.
е) Повторное объявление методов (перегрузка методов).
Повторное объявление обычных процедур и функций, а также методов позволяет создавать подпрограммы с одинаковыми именами, но с несколько различными возможностями. Исторически перегрузка впервые была введена в C++ для того, чтобы позволить использование нескольких конструкторов с одинаковым именем (именем класса). В ОР эта возможность не считалась необходимой просто потому, что здесь можно объявлять конструкторы с разными именами. Однако из-за интеграции Delphi и C++ Builder фирма Borland пошла на введение этой особенности в ОР.
Перегрузка нужна для того, чтобы произвести одинаковые или похожие действия с разнотипными данными. Виртуальными их сделать нельзя, поскольку тогда тип и число параметров должны совпадать.
Для указания компилятору о tqm, что подпрограммы, включая конструкторы и статические методы, имеют одинаковые имена, используется слово-директива Overload у каждой из них, при объявлении в одном классе или у предка и потомка. Подпрограммы, объявленные с директивой Overload, должны различаться или числом или типом параметров (тип результата функции не является различием). Оба перегружаемых метода доступны, даже если второй определен в классе-наследнике, поскольку компилятор определит различие в параметрах.
Есть два ограничения на перегрузку методов:
• нельзя дважды перегружать методы в разделе Published одного и того же класса;
• для объявления виртуального метода перегружаемым в классе-наследнике дополнительно добавляется слово-директива Reintroduce. Синтаксис применения директивы Reintroduce:
Procedure <имя метода>[(<параметры>)]; Reintroduce; Overload;
Type T1=Class
Procedure Test(I: Integer); Overload; Virtual;
End;
// В бачовом классе не обязательно помечать метод как Overload
T2=Class(T1)
Procedure Test(S: String); Reintroduce; Overload;
End;
Begin
SomeObject:=T2.Create;
SonieObject.Test('HeIlo'); // Фактически вызывается Т2.Test
SomeObject.Test(7); // Фактически вызывается Т1.Test
Tl(SomeObject).Test(7); // Можно и так, если известно имя – Т1
По отношению к методам перегрузка позволяет упростить доступ к одноименным методам родительского класса, не зная имя класса с одноименным методом.
ж) Дружественные классы.
В языке C++ с помощью ключевого слова friend реализуется концепция дружественных классов, т.е. классов, объектам которых разрешен доступ к Private полям и методам другого класса. В ОР подобного слова нет, однако объекты классов, описанных в одном модуле, имеют взаимный доступ ко всем разделам объектов другого класса. Таким образом фактически реализуется дружественность классов в Delphi.