我有一个可以保存接口的列表 我想要一个删除功能,只删除支持特定接口的项目。
type
TMyList<T: IFoo> = class
procedure Remove(const Item: T); overload;
procedure Remove<I: IBar>(const Item: T); overload;
end;
procedure TMyList<T>.Remove<I>(const Item: T);
begin
if Supports(Item, I) then Remove(Item);
end;
E2250没有超载版本的支持&#39;可以用这些参数调用
有没有办法可以做到这一点?
答案 0 :(得分:4)
是的,虽然您不能这样传递接口类型参数,但您可以传递TGUID
并将接口类型分配给TGUID
,前提是您在接口声明中声明了GUID以开始用。
实施例
type
IFoo = interface
['{93863A49-5014-4AE5-A7CF-F3F2E044CE57}'] //<Ctrl>+<Shift>+G
....
end;
IBar = interface(IFoo)
['{88888888-5014-4AE5-A7CF-F3F2E044CE57}']
....
end;
procedure TFooList.Remove(const Item: IFoo; const MustBeA: TGuid); {overload;}
begin
if Supports(Item, MustBeA) then Remove(Item);
....
for i:= 0 to count-1 do begin
//Only remove IBar16 items
MyFooList.Remove(FooList[i], IBar16);
end;
答案 1 :(得分:3)
首先,两个接口应该有一个用它们声明的GUID(如果你还没有这样做)。
type
IBar = interface
['{08C764E8-3EF4-42A7-94B7-8D1C5371DF25}']
end;
IFoo = interface
['{30B9440D-A012-4C7D-8422-A80D7E18F4E5}']
end;
然后,您应该能够将呼叫更改为&#34;支持&#34;对此:
uses System.TypInfo;
function TMyList<T>.Remove<I>(const Item: T);
begin
//if Supports(Item, I) then Remove(Item);
if Supports(Item, GetTypeData( TypeInfo(I) )^.GUID) then Remove(Item);
// ...
end;
虽然编译器没有&#34;知道&#34;那&#34;我&#34;是一种接口类型,你做 - 因为你限制它。因此,可以安全地从TypeData中提取GUID,用于&#34; I&#34;。
通用类型约束(类,接口或记录)不声明或细化引用或使用的代码中泛型参数的数据类型。相反,它们只是允许编译器限制泛型类型的使用方式。
type
IBar = interface
['{08C764E8-3EF4-42A7-94B7-8D1C5371DF25}']
end;
IFoo = interface
['{30B9440D-A012-4C7D-8422-A80D7E18F4E5}']
end;
IFoo1 = interface(IFoo)
['{6C3D06C9-C0B7-45CD-80F2-45123ECC5E9C}']
end;
IFoo2 = interface(IFoo)
['{9C3AB5F7-E88C-4620-AFC5-B83340048531}']
end;
TMyList<T: IFoo> = class
end;
&lt; T:IFoo&gt;约束将允许这些:
var
L : TMyList<IFoo>;
L : TMyList<IFoo1>;
L : TMyList<IFoo2>;
但不是这样:
L : TMyList<IBar>;
而且,最重要的是,在3次有效的扩展中,&#34; T&#34; 不成为接口类型。它仍然是通用的或&#34;类型未知&#34;在编译器的眼中。
&#34;构造函数&#34;约束是此规则的一个例外。它将要求泛型参数为类类型,但更重要的是,它允许通过无参数构造函数实例化目标类,而不使用类型转换。
type
TMyClass = class
constructor Create;
procedure DoSomething;
end;
constructor TMyClass.Create;
begin
end;
procedure TMyClass.DoSomething;
begin
end;
type
TMyGeneric2<T:constructor> = class
procedure Perform;
end;
procedure TMyGeneric2<T>.Perform;
var
x : T;
begin
x := T.Create; // This is allowed...
x.DoSomething; // ...but this is not.
end;
当您使用泛型类型参数约束时,您没有解析泛型参数的类型。您只需设置一些规则,以便编译器在使用该泛型类型时遵循。