Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Понимание наследования интерфейсов и функция `Supports` в Delphi: решение проблемы с неожиданным поведением компилятора

Delphi , Программа и Интерфейс , Интерфейс

Понимание наследования интерфейсов и функция Supports в Delphi: решение проблемы с неожиданным поведением компилятора

При работе с наследованием интерфейсов в Delphi иногда возникают ситуации, когда ожидаемое поведение не происходит. В данной статье мы рассмотрим одну из таких ситуаций и попробуем найти решение.

Описание проблемы

Рассмотрим простой пример иерархии классов и интерфейсов в Delphi:

+---------------+
| << IMyBase >> |
+---------------+
       ^
       |
+---------------+
| << IMyIntf >> |
+---------------+
       ^
       |
      +---------+
      | TMyObj  |
      +---------+

Автор столкнулся с проблемой: при попытке создания переменной типа IMyBase и инициализации её объектом TMyObj возникла ошибка несовместимости типов. Также, проверка поддержки интерфейса IMyBase через переменную типа IMyIntf не дала ожидаемого результата и возвращала false.

Пример кода

program interface_inheritance;
{$APPTYPE CONSOLE}
{$R *.res}
uses
  System.SysUtils;
type
  IMyBase = interface
    ['{CC7C61B8-3FBA-481F-AF0D-A93C603B5202}']
    procedure Hello;
  end;
  IMyIntf = interface(IMyBase)
    ['{01CE01D9-A753-431C-A30E-64BAEC6C4E26}']
    //
  end;
  TMyObj = class(TInterfacedObject, IMyIntf)
    procedure Hello;
  end;
procedure TMyObj.Hello;
begin
  Writeln('Hello World');
end;
var
  b: IMyBase;
  i: IMyIntf;
begin
  // Компилятор выдает ошибку E2010
  //b := TMyObj.Create;
  //b.Hello;

  // Не работает как ожидалось
  // Не вызывает Hello()
  i := TMyObj.Create;
  if Supports(i, IMyBase, b) then begin
    // Почему i не поддерживает IMyBase ??
    b.Hello;
  end;

  // Работает, но небезопасно!
  // Жесткое приведение, без проверки.
  i := TMyObj.Create;
  b := IMyBase(i);
  b.Hello;

  // Работает, конечно!
  i := TMyObj.Create;
  i.Hello;

  Readln;
end.

Подтвержденное решение

Проблема заключается в том, что класс TMyObj должен явно заявить о поддержке всех интерфейсов, от которых он наследуется. Правильный вариант объявления класса:

TMyObj = class(TInterfacedObject, IMyBase, IMyIntf)
  // ...
end;

Эта информация подтверждена ответом Дэнни Торпа, бывшего инженера Borland, на связанный вопрос:

Если класс не объявляет поддержку унаследованного интерфейса, то класс не будет совместим по назначению с переменными унаследованного интерфейса. Это связано с требованиями COM и ActiveX, которые не позволяют реализации поддерживать предка определенного интерфейса. Поскольку интерфейсы Delphi предназначены для совместимости с COM, это неожиданное поведение является следствием этой спецификации.

Альтернативное решение

Использование функции QueryInterface, которая позволяет получить указатель на интерфейс, поддерживаемый объектом, и может быть использована для решения подобных проблем.

var
  qb: IMyBase;
begin
  qb := i.QueryInterface<IMyBase>;
  if Assigned(qb) then
  begin
    qb.Hello;
  end;
end;

Заключение

При работе с наследованием интерфейсов в Delphi важно помнить о необходимости явного объявления поддержки всех интерфейсов, от которых наследуется класс. Это позволит избежать ошибок компиляции и обеспечит корректное выполнение программы.

Создано по материалам из источника по ссылке.

При работе с наследованием интерфейсов в Delphi возникают сложности с правильным объявлением поддержки интерфейсов классом, что приводит к ошибкам в процессе компиляции и неожиданному поведению программы.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Интерфейс ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-02-05 14:48:38/0.0037250518798828/0