Ошибка Delphi с обобщениями и интерфейсами

#delphi #generics #interface

#delphi #обобщения #интерфейс

Вопрос:

Следующий код Delphi не компилируется с ошибкой в функции Foo, но функция Foo2 компилируется. Это сводит меня с ума, у кого-нибудь есть идея?

 type

  IA<T> = Interface
  end;

  TA<T> = class(TInterfacedObject, IA<T>)
    function Foo<V> : IA<V>;
  end;

  TB<U,T> = class(TA<T>)
  end;

  TC = class
    function Foo2<T,V> : IA<V>;
  end;


implementation

{ TA<T> }

function TA<T>.Foo<V>: IA<V>;
begin
  Result := TB<T,V>.Create;
end;

{ TC }

function TC.Foo2<T,V>: IA<V>;
begin
  Result := TB<T,V>.Create;
end;
  

Ответ №1:

Это действительно выглядит странно, и я подозреваю, что это ошибка. Вы можете обойти это, объявив, что TB<U, T> реализует IA<T> . Изменить

 TB<U, T> = class(TA<T>)
  

Для

 TB<U, T> = class(TA<T>, IA<T>)
  

Обратите внимание, что ваш код со всеми удаленными дженериками компилируется:

 type
  IA = interface
  end;

  TA = class(TInterfacedObject, IA)
    function Foo: IA;
  end;

  TB = class(TA)
  end;

  TC = class
    function Foo2: IA;
  end;

function TA.Foo: IA;
begin
  Result := TB.Create;
end;

function TC.Foo2: IA;
begin
  Result := TB.Create;
end;
  

Это, по-видимому, подтверждает мою уверенность в том, что ваш код правильный и должен быть принят компилятором.

Комментарии:

1. Спасибо за ответ, но почему Foo2 работает без изменения объявления?

2. Как я уже сказал, для меня это выглядит как ошибка

3. Я думаю, это потому, что Foo2 явно ссылается на интерфейс. Foo on ссылается косвенно через класс TA, и поэтому необходимо указать TB, который реализует интерфейс.

4. @Dsm Я не понимаю. Тип, возвращаемый двумя функциями, идентичен, и код в двух функциях идентичен.

5. @DavidHeffernan Я знаю, но я видел похожие проблемы, о которых сообщалось на этом сайте, и это было причиной. Я думаю, что это по замыслу, возможно, безопасность превыше всего, если вы неявно используете интерфейс (через наследование), тогда вы должны объявить этот интерфейс в классе, который его использует.