Mat*_*ood 5 delphi inheritance interface delphi-2006
我正在尝试实现一个接口,将数据集中的记录转换为Delphi的pre-generics版本中的Delphi记录.我现在不喜欢这个界面,因为它总是需要调用支持,如果可能的话我想避免使用它,并且想知道是否有更好的方法可以让我失去它.
到目前为止,我已经定义了导航界面和数据检索界面:
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;
Run Code Online (Sandbox Code Playgroud)
基本上我有一个具体的基类,它包含一个私有数据集,IBaseRecordCollection
并为每个RecordCollection接口实现具体类,该接口派生自一个实现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;
Run Code Online (Sandbox Code Playgroud)
现在,为了使用这个,我不得不让一个生成器返回一个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;
Run Code Online (Sandbox Code Playgroud)
虽然这有效,但我并不热衷于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;
Run Code Online (Sandbox Code Playgroud)
但不幸的是,Delphi并不聪明,没有意识到IRecARecordCollection的实现是IBaseRecordCollection
在Collection属性implements
调用和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;
Run Code Online (Sandbox Code Playgroud)
没有编译.它抱怨TRec1RecordCollection
无法找到与之相关的方法IBaseRecordCollection
.我也尝试将Collection
属性从Abstract 移动到Rec1RecordCollection
并重新声明属性,TRec1RecordCollection
并使用相同的结果
看起来更深层似乎实现类的直接继承IBaseRecordCollection
可行,但Delphi无法通过使用属性间接处理它implements
.
你的代码几乎就在那里.代码中的implements指令无法编译,因为您只声明了您的类实现了派生接口.就目前而言,您的类没有实现implements指令引用的接口,即IBaseRecordCollection
.您可能认为这将从继承推断,但事实并非如此.
要解决您的问题,您只需要声明TRec1RecordCollection
实现两个接口:
type
TRec1RecordCollection = class(TInterfacedObject, IBaseRecordCollection,
IRecARecordCollection)
....
end;
Run Code Online (Sandbox Code Playgroud)
只做一个小改动,你的代码就会编译.
更新
您对问题的编辑会稍微改变一下.鉴于原始问题中的代码,我的答案中的代码确实可以编译.但是,添加任何方法IBaseRecordCollection
,编译将不接受它.
编译器应该接受这个代码,事实上它不是因为编译器错误.现代版本的Delphi将接受您对问题的更新中的代码.
除非您升级编译器,否则将无法使您的预期设计工作.