基本的に、クラスが同じジェネリック インターフェイスの 2 つの異なるバージョンを実装できるようにしたいと考えています。
このコードを検討してください
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 は予想どおり「Blah」を表示しますが、2 番目の ShowMessage はクラッシュします。クラッシュする理由は、呼び出しが予想どおり Val() ではなく T2Val() を呼び出すためです。どうやら、競合解決マッピングは、ITest: T2 だけでなく、両方のタイプのインターフェイスのメソッドをマップします。
それで、ここに私の質問があります。
これはバグですか?つまり、Embarcadero はこれをサポートすることを意図していたのに、単純に間違って実装したのでしょうか? それとも、プログラマーにこのようなことをさせるつもりはまったくなかったのでしょうか? (正直なところ、テスト プログラムがコンパイルされたことに少し驚きました)
これがバグである場合、1 つのクラスで 2 つの異なるタイプの単一のジェネリック インターフェイスをサポートできるようにするための回避策があるかどうか、誰にもわかりませんか?