По сути, я хочу, чтобы класс мог реализовать две разные версии одного и того же универсального интерфейса.
Рассмотрим этот код
type
// a generic interface
ITest<T> = interface
['{6901FE04-8FCC-4181-9E92-85B73264B5DA}']
function Val: T;
end;
// a class that purports to implement two different types of that interface
TTest<T1, T2> = class(TInterfacedObject, ITest<T1>, ITest<T2>)
protected
fV1: T1;
fV2: T2;
public
constructor Create(aV1: T1; aV2: T2);
function Val: T1; // Val() for ITest<T1>
function T2Val: T2; // Val() for ITest<T2>
function ITest<T2>.Val = T2Val; // mapping
end;
constructor TTest<T1, T2>.Create(aV1: T1; aV2: T2);
begin
inherited Create;
fV1 := aV1;
fV2 := aV2;
end;
function TTest<T1, T2>.T2Val: T2;
begin
result := fV2;
end;
function TTest<T1, T2>.Val: T1;
begin
result := fV1;
end;
/////////////
procedure Test;
var
t : TTest<integer, string>;
begin
t := TTest<integer, string>.Create(39, 'Blah');
ShowMessage((t as ITest<string>).Val); // this works as expected
ShowMessage(IntToStr((t as ITest<integer>).Val)); // this gets AV
end;
Первый ShowMessage отображает «Бла», как я и ожидал, но второй вылетает. Причина сбоя в том, что вызов вызывает T2Val() вместо Val(), как я и ожидал. Очевидно, сопоставление разрешения конфликтов сопоставляет метод для обоих типов интерфейсов, а не только для ITest: T2.
Итак, вот мой вопрос (ы).
Это ошибка? Под чем я подразумеваю, что Embarcadero намеревался поддерживать это и просто неправильно реализовывать? Или у них никогда не было намерения позволять программистам делать что-то подобное? (Честно говоря, я был немного удивлен, что моя тестовая программа вообще скомпилировалась)
Если это ошибка, кто-нибудь знает, может ли быть обходной путь, позволяющий мне иметь один класс, поддерживающий два разных типа одного универсального интерфейса?