如何正确使接口支持迭代? [英] How to properly make an interface support iteration?
问题描述
如何从界面公开此TList,如 IEnumerator
或 IEnumerator< IFungibleTroll>
?我正在使用Delphi XE。
这是我有多远:
单位FungibleTrollUnit;
接口
使用
Windows,消息,SysUtils,
变体,类,图形,
控件,表单,
泛型
type
IFungibleTroll = interface
['{03536137-E3F7-4F9B-B1F5-2C8010A4D019}']
函数GetTrollName:String;
函数GetTrollRetailPrice:Double;
结束
TFungibleTrolls = class(TInterfacedObject,IEnumerable< IFungibleTroll>)
protected
FTrolls:TList< IFungibleTroll> ;;
public
// IEnumerable
函数GetEnumerator:IEnumerator< IFungibleTroll> ;; //
//函数GetEnumerator:IEnumerator;超载;
//查找/搜索应用功能需要搜索。
//这个
函数FindSingleItemByName(aName:String; patternMatch:Boolean):IFungibleTroll;
函数FindMultipleItemsByName(aName:String; patternMatch:Boolean):IEnumerable< IFungibleTroll> ;;
函数FindSingleItemByIdentifier(anIdentifer:String):IFungibleTroll; //使用内部非可见标识符来查找应用程序。
构造函数创建;
属性巨魔:TList< IFungibleTroll>阅读FTrolls // implements IEnumerable< IFungibleTroll> ;;?
private
end;
实现
{TFungibleTrolls}
构造函数TFungibleTrolls.Create;
begin
FTrolls:= TList< IFungibleTroll> .Create;
end;
函数TFungibleTrolls.FindMultipleItemsByName(aName:String;
patternMatch:Boolean):IEnumerable< IFungibleTroll> ;;
begin
end;
函数TFungibleTrolls.FindSingleItemByIdentifier(
anIdentifer:String):IFungibleTroll;
begin
end;
函数TFungibleTrolls.FindSingleItemByName(aName:String;
patternMatch:Boolean):IFungibleTroll;
begin
end;
函数TFungibleTrolls.GetEnumerator:IEnumerator< IFungibleTroll> ;;
begin
result:= FTrolls.GetEnumerator;
结束
//函数TFungibleTrolls.GetEnumerator:IEnumerator;
// begin
// result:= FTrolls.GetEnumerator; // type IEnumerator< IFungibleTroll>或IEnumerator?
// end;
结束。
我陷入了三个错误之一,我无法弄清楚如何解决: p>
[DCC错误] FungibleTrollUnit.pas(26):E2252具有相同参数的方法GetEnumerator已存在
-or -
[DCC错误] FungibleTrollUnit.pas(19):E2291缺少接口方法的实现IEnumerable.GetEnumerator
-or-
[DCC错误] FungibleTrollUnit.pas(19):E2291缺少接口方法的实现IEnumerable.GetEnumerator
似乎我必须声明两种形式的GetEnumerator,如果我声明TFungibleTrolls实现IEnumerable,但我似乎无法弄清楚如何做,无论是重载或没有重载,或使用方法解析条款,如下所示:
function IEnumerable.GetEnumerator = GetPlainEnumerator; //需要方法解析条款?
函数GetEnumerator:IEnumerator< IFungibleTroll> ;;
函数GetPlainEnumerator:IEnumerator;
这可能看起来像是一个非常基本的使用IEnumerable,并使接口支持迭代,我被卡住了。
更新:在没有首先声明 List< T>
,由于 IEnumerable< T>
继承自 IEnumerable
的事实,我陷入了一个裂缝,但是,我的类不是单个获取枚举器方法,而是提供多个类,而且由于我的类不是通用的,所以它不能直接映射到IEnumerable的要求,除非我使用通用的列表< T>
声明。当编译成一个项目(.dproj + .dpr),而不是内置到一个包(.dproj + .dpk)并在IDE中编译时,Marjan的示例可以工作。它可以从命令行,一个包中,而不是在IDE中,在一个包中。
不直接回答你的问题(仍然在工作),但这是我做了一个接口枚举器,即接口类支持迭代:
IList< T> = interface(IInterface)
[...]
函数GetEnumerator:TList< T> .TEnumerator;
function Add(const Value:T):Integer;
结束
type
TBjmInterfacedList< T> = class(TBjmInterfacedObject,IList< T)
strict private
FList:TList< T>;
函数GetEnumerator:TList< T> .TEnumerator;
strict protected
function Add(const Value:T):Integer;
public
构造函数创建;覆盖
析构函数覆盖
结束
实现
构造函数TBjmInterfacedList< T>创建;
开始
继承;
FList:= TList< T>。创建;
结束
析构函数TBjmInterfacedList< T> .Destroy;
begin
FreeAndNil(FList);
继承;
结束
函数TBjmInterfacedList< T> .GetEnumerator:TList< T> .TEnumerator;
begin
结果:= FList.GetEnumerator;
结束
函数TBjmInterfacedList< T> .Add(const Value:T):整数;
begin
结果:= FList.Add(Value);
结束
然后,您可以执行以下操作:
ISite = interface(IInterface)
...
end;
ISites = interface(IList< ISite>);
...
end;
var
网站中的网站开始
...
end;
与实现类,如:
TSite = class(TBjmInterfacedObject,ISite)
...
end;
TSites = class(TBjmInterfacedList< ISite>,ISites)
...
end;
更新
示例项目源上传到
http://www.bjmsoftware.com/ delphistuff / stackoverflow / interfacedlist.zip
How can I expose this TList from an interface, as either IEnumerator
or IEnumerator<IFungibleTroll>
? I am using Delphi XE.
Here's how far I got:
unit FungibleTrollUnit;
interface
uses
Windows, Messages, SysUtils,
Variants, Classes, Graphics,
Controls, Forms,
Generics.Collections;
type
IFungibleTroll = interface
['{03536137-E3F7-4F9B-B1F5-2C8010A4D019}']
function GetTrollName:String;
function GetTrollRetailPrice:Double;
end;
TFungibleTrolls = class (TInterfacedObject,IEnumerable<IFungibleTroll>)
protected
FTrolls:TList<IFungibleTroll>;
public
// IEnumerable
function GetEnumerator:IEnumerator<IFungibleTroll>;//
// function GetEnumerator:IEnumerator; overload;
// find/search app feature requires searching.
// this
function FindSingleItemByName(aName:String;patternMatch:Boolean):IFungibleTroll;
function FindMultipleItemsByName(aName:String;patternMatch:Boolean):IEnumerable<IFungibleTroll>;
function FindSingleItemByIdentifier(anIdentifer:String):IFungibleTroll;// use internal non-visible identifier to find an app.
constructor Create;
property Trolls:TList<IFungibleTroll> read FTrolls; // implements IEnumerable<IFungibleTroll>;??
private
end;
implementation
{ TFungibleTrolls }
constructor TFungibleTrolls.Create;
begin
FTrolls := TList<IFungibleTroll>.Create;
end;
function TFungibleTrolls.FindMultipleItemsByName(aName: String;
patternMatch: Boolean): IEnumerable<IFungibleTroll>;
begin
end;
function TFungibleTrolls.FindSingleItemByIdentifier(
anIdentifer: String): IFungibleTroll;
begin
end;
function TFungibleTrolls.FindSingleItemByName(aName: String;
patternMatch: Boolean): IFungibleTroll;
begin
end;
function TFungibleTrolls.GetEnumerator: IEnumerator<IFungibleTroll>;
begin
result := FTrolls.GetEnumerator;
end;
//function TFungibleTrolls.GetEnumerator: IEnumerator;
//begin
// result := FTrolls.GetEnumerator; // type IEnumerator<IFungibleTroll> or IEnumerator?
//end;
end.
I get stuck in one of three errors that I can't figure out how to solve:
[DCC Error] FungibleTrollUnit.pas(26): E2252 Method 'GetEnumerator' with identical parameters already exists
-or-
[DCC Error] FungibleTrollUnit.pas(19): E2291 Missing implementation of interface method IEnumerable.GetEnumerator
-or-
[DCC Error] FungibleTrollUnit.pas(19): E2291 Missing implementation of interface method IEnumerable.GetEnumerator
It seems I must declare two forms of GetEnumerator, if I declare TFungibleTrolls to implement IEnumerable, but I can't seem to figure out how to do it, either with overloads, or without overloads, or using a "method resolution clause", like this:
function IEnumerable.GetEnumerator = GetPlainEnumerator; // method resolution clause needed?
function GetEnumerator:IEnumerator<IFungibleTroll>;
function GetPlainEnumerator:IEnumerator;
This probably seems like a pretty basic use of IEnumerable, and making an Interface support iteration, and yet, I'm stuck.
Update: It seems when I try to do this without first declaring a List<T>
, I am falling into a crack caused by the fact that IEnumerable<T>
inherits from IEnumerable
, and yet, instead of a single get enumerator method, my class must provide multiple ones, and because my class is not a generic, it can't "map itself" to IEnumerable's requirements directly unless I use a generic List<T>
declaration. Marjan's sample works, when compiled into a project (.dproj+.dpr) but not when built into a package (.dproj+.dpk) and compiled in the IDE. It works fine from the command line, in a package, but not in the IDE, in a package.
Not an answer to your question directly (still working on that), but this is what I did to get an "interfaced enumerator", ie and interfaced class that supports iteration:
IList<T> = interface(IInterface)
[...]
function GetEnumerator: TList<T>.TEnumerator;
function Add(const Value: T): Integer;
end;
type
TBjmInterfacedList<T> = class(TBjmInterfacedObject, IList<T>)
strict private
FList: TList<T>;
function GetEnumerator: TList<T>.TEnumerator;
strict protected
function Add(const Value: T): Integer;
public
constructor Create; override;
destructor Destroy; override;
end;
implementation
constructor TBjmInterfacedList<T>.Create;
begin
inherited;
FList := TList<T>.Create;
end;
destructor TBjmInterfacedList<T>.Destroy;
begin
FreeAndNil(FList);
inherited;
end;
function TBjmInterfacedList<T>.GetEnumerator: TList<T>.TEnumerator;
begin
Result := FList.GetEnumerator;
end;
function TBjmInterfacedList<T>.Add(const Value: T): Integer;
begin
Result := FList.Add(Value);
end;
And then you can do stuff like:
ISite = interface(IInterface)
...
end;
ISites = interface(IList<ISite>);
...
end;
var
for Site in Sites do begin
...
end;
with implementing classes like:
TSite = class(TBjmInterfacedObject, ISite)
...
end;
TSites = class(TBjmInterfacedList<ISite>, ISites)
...
end;
Update
Example project source uploaded to http://www.bjmsoftware.com/delphistuff/stackoverflow/interfacedlist.zip
这篇关于如何正确使接口支持迭代?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!