Basically, I want a class to be able to implement two different versions of the same generic interface.
Consider this code
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;
The first ShowMessage displays 'Blah' as I would expect, but the second crashes. The reason it crashes is because the call invokes T2Val() instead of Val() as I would have expected. Apparently the conflict resolution mapping maps the method for both types of interfaces and not just for ITest: T2.
So, here's my question(s).
Is this a bug? By which, I mean, did Embarcadero intend for this to be supported and simply implement it wrong? Or did they never have any intention of allowing programmers to do something like this at all? (Honestly, I was a little surprised that my test program even compiled)
If this is a bug, does anyone have any idea if there might be a workaround to let me have one class support two different types of a single generic interface?