Delphi接口和IList<T>(或TObjectList<T>)

4

我正在尝试实现Spring 4 Delphi,并仅对接口进行编程,而不是类。然而,当您想要使用TObjectList时,这似乎是不可能的。

请考虑以下代码:

unit Unit1;

interface

uses
  Spring.Collections,
  Spring.Collections.Lists;

type

  IMyObjParent = interface
  ['{E063AD44-B7F1-443C-B9FE-AEB7395B39DE}']
    procedure ParentDoSomething;
  end;

  IMyObjChild = interface(IMyObjParent)
  ['{E063AD44-B7F1-443C-B9FE-AEB7395B39DE}']
    procedure ChildDoSomething;
  end;

implementation

type
  TMyObjChild = class(TInterfacedObject, IMyObjChild)
  protected
    procedure ParentDoSomething;
  public
    procedure ChildDoSomething;
  end;


{ TMyObj }

procedure TMyObjChild.ChildDoSomething;
begin

end;

procedure TMyObjChild.ParentDoSomething;
begin

end;

procedure TestIt;
var
  LMyList: IList<IMyObjChild>;
begin
  TCollections.CreateObjectList<IMyObjChild>;
  //[DCC Error] Unit1.pas(53): E2511 Type parameter 'T' must be a class type
end;

end.

我知道我可以在上面的例子中将IMyObjChild更改为TMyObjChild,但如果我需要在另一个单元或表单中使用它,该怎么办?

仅编程到接口似乎太难或不可能,一旦你需要一个TObjectList。

烦死了... 有什么想法或帮助吗?


3
您可以使用 TInterfaceList。 - Toon Krijthe
2
如果您使用接口,就不需要TObjectList,因为它所做的一切都是在TList的基础上管理其持有的对象的生命周期。 - Stefan Glienke
谢谢!我已经为此苦苦挣扎了几天,但由于接口是引用计数的,所以可以使用TList而不是TObjectList。 - Rick Wheeler
1
就此而言,你的接口似乎具有完全相同的GUID。这可能会成为一个问题。每个接口应该有一个不同的GUID。在编辑器中使用Shift+Ctrl+G生成一个新的GUID。 - Rudy Velthuis
1个回答

6

CreateObjectList有一个泛型约束,它的类型参数必须是一个类:

function CreateObjectList<T: class>(...): IList<T>;

您的类型参数不符合约束,因为它是一个接口。对象列表的特点在于它包含对象。如果您查看Spring.Collections.Lists中的TObjectList,您将会发现它也有一个泛型约束,即其类型参数必须是一个类。由于CreateObjectList将创建一个TObjectList<T>,因此它必须反映该类型约束。
TObjectList<T>的存在意义在于通过OwnsObjects来承担其成员的所有权,这与同名的经典Delphi RTL类别非常相似。当然,您持有的是接口,因此您根本不需要这个功能。您应该调用CreateList。即使您通过IList<T>接口引用它,您仍然只需要一个简单的TList<T>。
LMyList := TCollections.CreateList<IMyObjChild>;

太好了,非常感谢你和Stefan! - Rick Wheeler
现在看来似乎很明显,但是我已经使用TObjectList这么长时间了,以至于在转换为接口时,我只是假定我需要继续使用它。再次感谢,这对我来说真的非常令人兴奋 :-D - Rick Wheeler
1
对于那些习惯于遗留的Contnrs.TObjectList的开发人员而言,似乎想要将其用于所有方面是很常见的。只有在打算将OwnsObjects设置为True时才需要使用TObjectList。否则,纯通用的TList<T>就很好了。即使是针对对象也是如此。TObjectList<T>的唯一目的是拥有对象。但由于在非泛型Delphi中,它减少了与简单TList相比的转换量,因此开发人员学会了使用它。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接