Совместимость класса и интерфейса

Интерфейсной переменной можно присвоить значение объектной переменной при условии, что объект (точнее его класс) реализует упомянутый интерфейс:

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 
               // не реализует
                // интерфейс IExtendedTextReader.
  ...
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;

 

Яндекс цитирования