- •С примерами на Object pascal (72 часа)
- •Введение
- •1.1. Основной принцип структурного программирования
- •1.2. Основные задачи структурного программирования
- •1.3. Основные принципы объектно-ориентированного программирования (ооп)
- •2.1. Алфавит языка pascal. Идентификаторы.
- •2.2. Простые и составные специальные символы, используемые на пк.
- •2.3. Стандартные типы данных. Двоичное представление чисел и дополнительный код.
- •2.4. Особенности работы с некоторыми типами данных
- •2.5. Арифметические операторы.
- •2.6. Логические операторы и операции отношения.
- •2.7. Потеря точности, потеря порядка и переполнение при арифметических операциях.
- •2.8. Структура простейшей программы.
- •2.9. Простейшие операторы языка Object pascal
- •1) Цикл от меньшего к большему значению:
- •2) Цикл от большего к меньшему значению:
- •2.10. Структурные типы данных
- •2.11. Указатели. Динамические переменные. Динамическое выделение и высвобождение памяти
- •2.12. Процедуры и функции. Формальные и фактические параметры. Передача параметров по ссылке, по значению и через указатель.
- •2.13. Локальные и глобальные переменные. Побочный эффект функции. Вложенность процедур и функций. Правила видимости.
- •2.14. Пример на правила видимости и передачи параметров
- •2.15. Рекурсия
- •2.1. Инкапсуляция. Объект. Поля данных и методы объекта
- •3.2 Задание модуль класса (статическая объектная модель)
- •4.10. Создание и уничтожение объектов. Конструкторы и деструкторы.
- •4.11. Наследование. Статические, виртуальные, динамические и абстрактные методы.
- •4.12. Области видимости объектов.
- •4.13. Обработка исключительных ситуаций.
- •4.14. Специальные средства для работы с ms Windows: сообщения.
- •4.15. События и их делегирование. Обработка событий.
- •4.16. Методы класса и указатели на класс.
- •4.17. Дополнительные возможности Object Pascal.
- •5. Визуальное проектирование в среде Delphi.
- •5.8. Создание экранных форм. Инспектор объектов.
- •5.9. Палитра компонентов.
- •6. Интерфейсы и множественное наследование
- •6.1. Общие представления об интерфейсах в Object pascal
- •6.2. Реализация интерфейсов свойством
- •6.3. Различение имен при реализации нескольких интерфейсов
- •5.11. Спецификаторы вызовов процедур и функций
- •5.12. Динамические массивы
- •5.13. Перезагрузка (overloading) методов, процедур и функций
- •5.14. Параметры по умолчанию
- •5.17. Технологии dde и ole
- •5.18. Технология ActiveX
- •5.20. Использование библиотек OpenGl и glu
- •5.21. Создание программистом собственного компонента Литература
6. Интерфейсы и множественное наследование
6.1. Общие представления об интерфейсах в Object pascal
Интерфейс объекта определяют методы и свойства, которые могут быть реализованы классом-наследником этого интерфейса. Они описываются аналогично абстрактным классам, так же, как абстрактные классы, но в отличие от них, не могут иметь экземпляров, не могут иметь реализации никаких своих методов (в Object PASCAL допускается реализация части методов в абстрактные классы). Реализация методов интерфейсов осуществляется в классе, поддерживающем (наследующем) данный интерфейс. Переменная типа интерфейс - это ссылка. Она дает возможность ссылаться на объект, чей класс реализует данный интерфейс. Однако с помощью такой переменной разрешается вызывать только методы, декларированные в данном интерфейсе, а не любые методы данного объекта. Интерфейсы являются альтернативой множественному наследованию, имеют практически все его достоинства и лишены его недостатков. Их использование существенно для написания ПО для распределенных систем на основе COM (the Component Object Model) и CORBA (Common Object Request Broker Architecture). Объекты, поддерживающие интерфейсы, могут взаимодействовать с COM- объектами, написанными на C++ или Java.
Интерфейсы, как и классы, могут быть описаны только в самой наружной области видимости программы или модуля, но не в процедуре или функции. Описание типа для интерфейса имеет вид:
type
interfaceName =
interface (ancestorInterface)
['{GUID}']
список полей
end;
Отличия от классов:
Не бывает экземпляров, реализующих тип интерфейс.
Список полей интерфейса может включать только свойства и методы. Поля данных использовать нельзя. Соответственно, спецификаторы read и write должны быть методами.
Все поля интерфейса всегда имеют тип видимости public (без явного указания); не разрешено использовать спецификаторов видимости (но у массивов может быть использован спецификатор default).
Не бывает конструкторов и деструкторов.
Методы не могут быть специфицированы как виртуальные, динамические, перекрытые, абстрактные. Поскольку они не имеют реализации в экземплярах типа, эти различия не имеют значения.
Наследование через интерфейсы множественное.
Реализация интерфейса может быть только в классе, при этом он должен реализовать все методы интерфейса (а значит, и все свойства)
Интерфейс, как и класс, наследует все методы прародителя, однако только на уровне абстракций, без реализации методов. Однако интерфейс наследует право реализации этих методов в классе, поддерживающем этот интерфейс. В декларации интерфейса можно указать, что интерфейс наследуется от прародительского интерфейса. Если такого указания нет, то интерфейс является непосредственным потомком IUnknown, который определен в модуле System и является прародителем для всех интерфейсов. В IUnknown продекларировано 3 метода — QueryInterface, _AddRef, Release. QueryInterface предназначен для поддержки интерфейсов объектов. _AddRef, _Release обеспечивают управление ссылками на интерфейсы. Простейший путь реализовать эти методы — создать класс-наследник от tInterfacedObject , описанного в модуле System.
Пример описания интерфейса:
type
IMalloc =
interface(IUnknown)
['{00000002-0000-0000-C000-000000000046}']
function Alloc(Size: Integer): Pointer; stdcall;
functionRealloc(P:Pointer;Size:Integer):Pointer;stdcall;
procedure Free(P: Pointer); stdcall;
function GetSize(P: Pointer): Integer; stdcall;
function DidAlloc(P: Pointer): Integer; stdcall;
procedure HeapMinimize; stdcall;
end;
Перед использованием продекларированного интерфейса он должен быть реализован в классе. Реализация осуществляется с помощью декларации в списке прародителей класса:
type
className =
class (ancestorClass,interface1,...,interfaceN)
memberList
end;
Например,
type
TMemoryManager =
class(TInterfacedObject, IMalloc, IErrorInfo)
...
end;
Когда класс реализует интерфейс, он должен реализовать (или наследовать реализацию) каждого метода, декларированного в интерфейсе. Ниже приведено описание tInterfacedObject из модуля System:
type
TInterfacedObject =
class(TObject, IUnknown)
protected
FRefCount: Integer;
function QueryInterface(const IID: TGUID; out Obj): Integer; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
public
property RefCount: Integer read FRefCount;
end;
tInterfacedObject реализует интерфейс. Поэтому в нем описаны и реализованы все три метода IUnknown. Классы, реализующие интерфейсы, могут быть использованы как прародители. Класс tInterfacedObject реализует три метода интерфейса IUnknown и поэтому удобен как прародитель для всех классов, реализующих интерфейсы. Когда интерфейс реализован в классе, каждый из его методов реализован соответствующим методом (по умолчанию с тем же именем) и с такой же сигнатурой.
В классе-наследнике можно перекрыть методы реализуемого интерфейса. При этом соответствующий метод должен быть виртуальным или динамическим). Также возможно заново унаследовать интерфейс:
type
IWindow =
interface
['{00000115-0000-0000-C000-000000000146}']
procedure Draw;
...
end;
TWindow =
class(TInterfacedObject, IWindow) //TWindow реализует IWindow
procedure Draw;
...
end;
TFrameWindow =
class(TWindow, IWindow) //TFrameWindow переопределяет реализацию Iwindow
procedure Draw;
...
end;
При этом в классе все методы от прародительской реализации этого интерфейса запираются (не наследуются), в том числе выражения различения методов.