Совместимость класса и интерфейса
Интерфейсной переменной можно присвоить значение объектной переменной при условии, что объект (точнее его класс) реализует упомянутый интерфейс:
var Intf: ITextReader; // интерфейсная переменная Obj: TTextReader; // объектная переменнаяbegin ... Intf := Obj; // В переменную Intf копируется ссылка на объект Obj ...end; |
Такая совместимость сохраняется в производных классах. Если класс реализует некоторый интерфейс, то и все его производные классы совместимы с этим интерфейсом (см. рисунок 6.3):
type TTextReader = class(TInterfacedObject, ITextReader) ... end; TDelimitedReader = class(TTextReader) ... end; var Intf: ITextReader; // интерфейсная переменная Obj: TDelimitedReader; // объектная переменнаяbegin ... Intf := Obj; ...end; |
Рисунок 6.3. Классы TTextReader, TDelimitedReader и TFixedReader совместимы с интерфейсом ITextReader
Однако, если класс реализует производный интерфейс, то это совсем не означает, что он совместим с базовым интерфейсом (см. рисунок 6.4):
type ITextReader = interface(IInterface) ... end; IExtendedTextReader = interface(ITextReader) ... end; TExtendedTextReader = class(TInterfacedObject, IExtendedTextReader) ... end; var Obj: TExtendedTextReader; Intf: ITextReader;begin ... Intf := Obj; // Ошибка! Класс TExtendedTextReader не реализует // интерфейс ITextReader. ...end; |
Рисунок 6.4. Класс TExtendedTextReader совместим лишь с интерфейсом IExtendedTextReader
Для совместимости с базовым интерфейсом нужно реализовать этот интерфейс явно:
type TExtendedTextReader = class(TInterfacedObject, ITextReader, IExtendedTextReader) ... end; |
Теперь класс TExtendedTextReader совместим и с интерфейсом ITextReader, поэтому следующее присваивание корректно:
Intf := Obj; |
Исключением из только что описанного правила является совместимость всех снабженных интерфейсами объектов с интерфейсом IInterface:
var Obj: TExtendedTextReader; Intf: IInterface;begin ... Intf := Obj; // Правильно, IInterface – особый интерфейс. ...end; |
Дата добавления: 2016-02-09; просмотров: 731;