Читайте также:
|
|
При множественном наследовании у класса может быть более одного предка. В этом случае класс наследует методы всех предков. Достоинства такого подхода в большей гибкости. Множественное наследование реализовано в C++. Из других языков, предоставляющих эту возможность, можно отметить Python и Эйфель. Множественное наследование поддерживается в языке UML.
Предок:
TAncestor = class
private
protected
public
// Виртуальная процедура
procedure VirtualProcedure; virtual; abstract;
procedure StaticProcedure;
end;
Наследник:
TDescendant = class(TAncestor)
private
protected
public
// Перекрытие виртуальной процедуры
procedure VirtualProcedure; override;
procedure StaticProcedure;
end;
18. Совместимость типов.
Совместимость типов требуется при конструировании выражений, а также при вызовах подпрограмм (для параметров-значений). Совместимость означает, что для переменных этих типов возможна операция присваивания - хотя во время этой операции присваиваемое значение может измениться: произойдет неявное приведение типов данных (см. п. "Приведение типов данных" ниже).
Два типа Т1 и Т2 будут совместимыми, если верен хотя бы один вариант из перечисленных ниже:
ñ Т1 и Т2 эквивалентны (в том числе совпадают);
ñ Т1 и Т2 - оба целочисленные или оба вещественные;
ñ Т1 и Т2 являются подмножествами одного типа;
ñ Т1 является некоторым подмножеством Т2;
ñ Т1 - строка, а Т2 - символ (см. лекцию 5);
ñ Т1 - это тип pointer, а Т2 - типизированный указатель (см. лекцию 10);
ñ Т1 и Т2 - оба процедурные, с одинаковым количеством попарно эквивалентных параметров, а для функций - с эквивалентными типами результатов (см. лекцию 8).
19. Полиморфизм и позднее связывание.
Полиморфизм — это возможность использовать одинаковые имена для методов, входящих в различные классы.
Концепция полиморфизма обеспечивает при применении метода к объекту использование именно того метода, который соответствует классу объекта.
Пусть определены три класса, один из них является базовым для двух других:
type
// базовый класс
TPerson=class
fname:string;{ имя }
constructor Create(name:string);
function info: string; virtual;
end;
// производный от базового TPerson
TStud=class(TPerson)
fgr:integer; { номер группы }
constructor Create(name:string;gr:integer);
function info: string; override;
end;
// производный от базового TPerson
TProf=class(TPerson)
fdep:string; { название кафедры }
constructor Create(name:string;dep:string);
function info: string; override;
end;
В каждом из этих классов определен метод info. В базовом классе с помощью директивы virtual метод info объявлен виртуальным. Объявление метода виртуальным дает возможность дочернему классу произвести замену виртуального метода своим собственным. В каждом дочернем классе определен свой метод info, который замещает соответствующий метод родительского класса. При этом метод порожденного класса, замещающий виртуальный метод родительского класса, помечается директивой override. Ниже приведено определение метода info для каждого класса.
function TPerson.info:string;
begin
result:=’’;
end;
function TStud.info:string;
begin
result:=fname+' гp.'+IntTostr(fgr);
end;
function TProf.info:string;
begin
result:=fname+'каф.'+fdep;
end;
Поздним связыванием (late binding) называется технология, которая позволяет создавать экземпляр определенного типа и вызывать его члены во время выполнения без кодирования факта его существования жестким образом на этапе компиляции. При создании приложения, в котором предусмотрено позднее связывание с типом из какойто внешней сборки, добавлять ссылку на эту сборку нет никакой причины, и потому в манифесте вызывающего кода она непосредственно не указывается.
20. Виртуальные и динамические методы.
Правила контроля соответствия типов (typecasting) языка Object Pascal гласят, что объекту как указателю на экземпляр объектного типа может быть присвоен адрес любого экземпляра любого из его дочерних типов. В процедуре ShowData параметр описан как TField - это значит, что в нее можно передавать объекты классов И TStringField, И TIntegerField, И TExtendedField, и любого другого потомка Класса TField.
Но какой (точнее, чей) метод GetData при этом будет вызван? Тот, который соответствует классу фактически переданного объекта. Этот принцип называется полиморфизмом, и он, пожалуй, представляет собой наиболее важный козырь ООП. Допустим, вы имеете дело с некоторой совокупностью явлений или процессов. Чтобы смоделировать их средствами ООП, нужно выделить их самые общие, типовые черты. Те из них, которые не изменяют своего содержания, должны быть реализованы в виде статических методов. Те же, которые изменяются при переходе от общего к частному, лучше облечь в форму виртуальных методов. Основные, "родовые" черты (методы) нужно описать в классе-предке и затем перекрывать их в классах-потомках. В нашем примере программисту, пишущему процедуру вроде ShowData, важно лишь, что любой объект, переданный в нее, является потомком TField и он умеет сообщить о значении своих данных (выполнив метод GetData). Если, к примеру, такую процедуру скомпилировать и поместить в динамическую библиотеку, то эту библиотеку можно будет раз и навсегда использовать без изменений, хотя будут появляться и новые, неизвестные в момент ее создания классы-потомки TField!
Наглядный пример использования полиморфизма дает среда Delphi. В ней имеется класс TComoonent. на уровне которого сосредоточены определенные "правила" взаимодействия компонентов со средой разработки и с другими компонентами. Следуя этим правилам, можно порождать от TComponent с-зон компоненты, настраивая Delphi на решение специальных задач. Теперь, надеемся, стало более или менее ясно, какие преимущества ООП лили ему стать основным способом разработки серьезного программного обеспечения. Те, кто начинал программировать еще для Windows 3.0, наверняка помнят, сколько усилий требовалось для написания совершенно тривиального кода. Сейчас для того же самого в Delphi достаточно буквально пары щелчков мышью! На самом деле именно сложность программирования для Windows стала катализатором внедрения ООП.
Теперь — подробнее о виртуальных и динамических методах. Если задуматься над рассмотренным выше примером, становится ясно, что у компилятора нет возможности определить класс объекта, фактически переданного в процедуру showData. Нужен механизм, позволяющий определить это прямо во время выполнения — это называется поздним связыванием (late binding). Естественно, такой механизм должен быть связан с передаваемым объектом. В качестве такого механизма служат таблица виртуальных методов (Virtual Method Table, VMT) и таблица динамических методов (Dynamic Method Table, DMT).
Разница между виртуальными и динамическими методами заключается в особенности поиска адреса. Когда компилятор встречает обращение к виртуальному методу объекта, он подставляет вместо прямого вызова по конкретному адресу код, который обращается к VMT этого объекта и извлекает оттуда нужный адрес. Такая таблица одна для каждого класса (объектного типа). В ней хранятся адреса всех виртуальных методов класса, независимо от того, унаследованы ли они от предка или перекрыты в данном классе. Отсюда и достоинства и недостатки виртуальных методов: они вызываются сравнительно быстро, однако для хранения указателей на них в таблице VMT требуется большое количество памяти.
Динамические методы вызываются медленнее, но позволяют более экономно расходовать память. Каждому динамическому методу системой присваивается уникальный индекс. В таблице динамических методов класса хранятся индексы и адреса только тех динамических методов, которые описаны в данном классе. При вызове динамического метода происходит поиск в этой таблице; в случае неудачи просматриваются таблицы DMT всех классов-предков в порядке иерархии и, наконец, TObject, где имеется стандартный обработчик вызова динамических методов. Для перекрытия и виртуальных, и динамических методов служит новая директива override, с помощью которой (и только с ней!) можно переопределять оба этих типа методов.
Дата добавления: 2015-11-16; просмотров: 46 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Создание и удаление объектов. | | | Понятие класса. Понятие метода. Представление метода в виде обычной процедуры. Понятие конструктора и деструктора. |