加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 没有泛型的接口继承

发布时间:2020-12-15 09:32:22 所属栏目:大数据 来源:网络整理
导读:我正在尝试实现一个接口,将数据集中的记录转换为Delphi的pre-generics版本中的Delphi记录.我现在不喜欢这个界面,因为它总是需要调用支持,如果可能的话我想避免使用它,并且想知道是否有更好的方法可以让我失去它. 到目前为止,我已经定义了导航界面和数据检索
我正在尝试实现一个接口,将数据集中的记录转换为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;

基本上我有一个包含私有数据集的具体基类,并为每个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;

虽然这有效,但我并不热衷于支持调用和混合我的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属性实现调用和TRec1RecordCollection对象的基础IBaseRecordCollection上拆分的.

是否还有其他建议可以采用更简洁的方法来实现这一目标?

– 编辑以回复@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,IRec1RecordCollection,IBaseRecordCollection)
private
  function GetRec: TRec1;
public
  property Rec: TRec1 read GetRec;
end;

没有编译.它抱怨TRec1RecordCollection无法找到与IBaseRecordCollection相关的方法.我还尝试将Collection属性从Abstract移动到Rec1RecordCollection,并在TRec1RecordCollection中重新声明属性,但结果相同

看起来更深层似乎实现IBaseRecordCollection的类的直接继承可行,但Delphi无法通过使用implements的属性间接处理它.

解决方法

你的代码几乎就在那里.代码中的implements指令无法编译,因为您只声明了您的类实现了派生接口.就目前而言,您的类没有实现implements指令引用的接口,即IBaseRecordCollection.您可能认为这将从继承推断,但事实并非如此.

要解决您的问题,您只需要声明TRec1RecordCollection实现两个接口:

type
  TRec1RecordCollection = class(TInterfacedObject,IRecARecordCollection)
  ....
  end;

只做一个小改动,你的代码就会编译.

更新

您对问题的编辑会稍微改变一下.鉴于原始问题中的代码,我的答案中的代码确实可以编译.但是,将任何方法添加到IBaseRecordCollection中,编译将不接受它.

编译器应该接受这个代码,事实上它不是因为编译器错误.现代版本的Delphi将接受您对问题的更新中的代码.

除非您升级编译器,否则将无法使您的预期设计工作.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读