Delphi 不同子代数据模块上具有主数据的主/详细客户端数据集:如何从代码中引用它们?

Delphi 不同子代数据模块上具有主数据的主/详细客户端数据集:如何从代码中引用它们?,delphi,inheritance,Delphi,Inheritance,我有一个名为RequestData的TClientDataSet的数据模块TDataModuleBase 我有两个数据模块从TDataModuleBasis下降,两个数据模块都有一个额外的TClientDataSet, 让我们用Task1Data将它们命名为TDataModuleTasks1,用Task2Data将它们命名为TDataModuleTasks2 任务有请求,因此RequestData是Task1Data或Task2Data的详细信息表。 Task1Data和Task2Data有一个

我有一个名为RequestData的TClientDataSet的数据模块TDataModuleBase

我有两个数据模块从TDataModuleBasis下降,两个数据模块都有一个额外的TClientDataSet, 让我们用Task1Data将它们命名为TDataModuleTasks1,用Task2Data将它们命名为TDataModuleTasks2

任务有请求,因此RequestData是Task1Data或Task2Data的详细信息表。 Task1Data和Task2Data有一个指向RequestData查询的持久字段,这些TclientDataSet后面的查询是为适当的主/详细关系设置的。这些查询实际上位于我们连接到的服务器应用程序中

“我的表单”有一个名为EditDataModule的通用TDataModule属性,该属性始终设置为指向表单所需的数据模块, 因此,我在Form1上的代码引用TDataModuleTasks1EditDataModule,在Form2上的代码引用TDataModuleTasks2EditDataModule

我现在有了从Form1或Form2创建/使用的FormX,它需要使用RequestData和Task1Data/Task2Data。 创建后,我设置FormX.EditDataModule:=Form1.EditDataModule或FormX.EditDataModule:=Form2.EditDataModule

现在,当我想在FormX中使用RequestData时,我可以在代码中使用TDataModuleBasiedDataModule,因为TDataModuleBasis是TDataModuleTasks1和TDataModuleTasks2的祖先

但是我还需要访问主clientdataset,假设它是一个属性数据集。 我是和你一起做的

if (EditDataModule is TDataModuleTasks1) then
   FTaskDataSet := TDataModuleTasks1(EditDataModule).Task1Data
else   
   if (EditDataModule is TDataModuleTasks2) then
      FTaskDataSet := TDataModuleTasks2(EditDataModule).Task2Data
   else
      Assert(error);   
问题:

是否有一种更“通用”的方法来引用主数据集而不使用Is测试和强制转换?例如,我可以通过RequestData联系他们吗


[顺便说一句,实际上,我的Task1Data和Task2Data都被命名为TaskData,但我在这里给了它们单独的名称。]

我会尝试将属性作为

TDataModuleBasis = class(TDataModule)
protected
  function GetTaskData: TClientDataSet; virtual; 
public
  property TaskData: TClientDataSet read GetTaskData;
end;
然后重写基函数GetTaskData:TClientDataSet;在TDataModuleTasks1和TDataModuleTasks2中,函数返回相应的TClientDataSet,如

TDataModuleTasks1 = class(TDataModuleBasis)
private
....
protected
  function GetTaskData: TClientDataSet; override;
public
....
end;

....

function TDataModuleTasks1.GetTaskData: TClientDataSet;
begin
  Result := (*the client data set object*)
end;
另一种方法是声明一个FTaskClientDataSet字段,并在TDataModuleBasis中引入构造函数或属性,然后通过访问任务集


因此,您可以使用TDataModuleBasisRequestData.Parent.TaskData访问TaskData

如果您使用纯代码访问数据集,则可以使用虚拟函数getter将其作为属性公开,然后在子类中重写该函数。然后您可以使用EditDataModule。TaskData和多态性将处理其余的。@Andy_D为什么我没有想到这一点?;-聪明,谢谢。但是,在写一个真实的答案的时候,你就知道了。没有什么能阻止我添加我的评论作为答案,而你却接受了它!:您的第一个方法给了我错误,我不愿意用{$WARN\u ABSTRACT OFF}禁用这些警告。我遗漏了摘要,这对解决方案来说是不必要的。此外,您在受保护/私有部分的替代位置也会导致提示。我已将两者都放在受保护部分。我已经相应地编辑了您的答案。我首先省略了摘要,但考虑了假设基础。如果函数不是抽象的,则将其保留为空。因为当调用派生的.Get if Basis.Get是抽象的,而不是在派生中重写时,就会出现一个抽象错误,人们应该说,哦,我应该重写它。这就是我对abstract=作为visibility lovering的观点,这是我第一次有意的,我认为没有必要从TDataModuleTasksN派生。但这种方式具有更大的灵活性,因为如果需要,可以和/或需要从TDataModuleTasksN派生类型。