【发布时间】:2013-10-04 00:49:49
【问题描述】:
我正在尝试实现一个接口,以将数据集中的记录转换为 Delphi 的预泛型版本中的 Delphi 记录。目前我不喜欢这个界面,因为它总是需要调用 Supports,如果可能的话我想避免这种情况,并且想知道是否有更好的方法可以做到这一点。
到目前为止,我已经定义了导航界面和数据检索界面:
IBaseRecordCollection = interface
procedure First;
procedure Next;
function BOF: boolean;
... // other dataset nav stuff
end;
IRecARecordCollection = interface
function GetRec: TRecA;
end;
IRecBRecordCollection = interface
function GetRec: TRecB;
end;
基本上,我有一个具体的基类,它包含一个私有数据集并为每个 RecordCollection 接口实现IBaseRecordCollection 和具体类,该接口派生自实现IBaseRecordCollection 的抽象类(由implements 属性处理)与实现记录检索例程:
TAbstractTypedRecordCollection = class(TInterfacedObject, IBaseRecordCollection)
private
FCollection: IBaseRecordCollection;
protected
property Collection: IBaseRecordCollection read FCollection implements IBaseRecordCollection;
public
constructor Create(aRecordCollection: IBaseRecordCollection);
end;
TRec1RecordCollection = class(TAbstractTypedRecordCollection, IRecARecordCollection);
public
function GetRec: TRecA;
end;
现在,要使用它,我不得不有一个返回 IRecARecordCollection 的构建器,然后乱用 Supports,我不喜欢它,因为它总是以这种方式使用。
即
procedure GetMyRecASet;
var
lRecARecordCollection: IRecARecordCollection;
lRecordCollection: IBaseRecordCollection;
begin
lRecARecordCollection := BuildRecACollection;
if not supports(lRecARecordCollection, IBaseRecordCollection, lRecordCollection) then
raise exception.create();
while not lRecordCollection.EOF do
begin
lRecARecordCollection.GetRec.DoStuff;
lRecordCollection.Next;
end;
end;
虽然这可行,但我并不热衷于 supports 调用并像这样混合我的 lRecordCollections 和我的 lRecARecordCollections。我原本希望能够做这样的事情:
IBaseRecordCollection = interface
// DBNav stuff
end;
IRecARecordCollection = interface (IBaseRecordCollection)
function GetRec: TRecA;
end;
TRec1RecordCollection = class(TInterfacedObject, IRecARecordCollection)
private
FCollection: IBaseRecordCollection;
protected
property Collection: IBaseRecordCollection read FCollection implements IBaseRecordCollection;
public
function GetRec: TRecA;
end;
但不幸的是,Delphi 不够聪明,无法意识到 IRecARecordCollection 的实现被拆分为 Collection 属性 implements 调用中的基础 IBaseRecordCollection 和 TRec1RecordCollection 对象。
对于实现这一目标的更简洁的方法,还有其他建议吗?
-- 编辑以对@David 的回答给出比评论中可能的(更长的)回复
建议的解决方案:
IBaseRecordCollection = interface ['{C910BD0A-26F4-4682-BC82-605C4C8F9173}']
function GetRecNo: integer;
function GetRecCount: integer;
function GetFieldList: TFieldList;
function EOF: boolean;
function BOF: boolean;
...
end;
IRec1RecordCollection = interface (IBaseRecordCollection) ['{E12F9F6D-6D57-4C7D-AB87-8DD50D35DCA2}']
function GetRec: TRec1;
property Rec: TRec1 read GetRec;
end;
TAbstractTypedRecordCollection = class(TInterfacedObject, IBaseRecordCollection)
private
FCollection: IBaseRecordCollection;
protected
property Collection: IBaseRecordCollection read FCollection implements IBaseRecordCollection;
public
constructor Create(aRecordCollection: IBaseRecordCollection);
end;
TRec1RecordCollection = class(TAbstractTypedRecordCollection, IRec1RecordCollection, IBaseRecordCollection)
private
function GetRec: TRec1;
public
property Rec: TRec1 read GetRec;
end;
没有编译。它抱怨TRec1RecordCollection 找不到与IBaseRecordCollection 相关的方法。我还尝试将 Collection 属性从 Abstract 移动到 Rec1RecordCollection 并在 TRec1RecordCollection 中重新声明该属性,结果都相同
看起来更深入一点,实现 IBaseRecordCollection 的类的直接继承似乎可以工作,但 Delphi 无法通过使用 implements 的属性间接地处理它。
【问题讨论】:
-
为了完整起见,由于 D2006 编译器中似乎存在一个错误(A 错误????),这意味着下面的@David 的解决方案不起作用我有必须砍掉依赖注入,只让所有 TRecXRecordCollections 从具体的 TBaseRecordCollection 继承而不是 TAbstractTypedRecordCollection
标签: delphi inheritance interface delphi-2006