4

我正在编写一些针对两个版本非常相似的硬件的软件,在我使用 API 初始化硬件之前,我无法知道我将返回哪种类型的硬件。

因为硬件非常相似,我计划有一个父类(TParent),它有一些抽象方法(对于硬件不同的地方),然后是两个子类(TChildA,TChildB),它们以硬件相关的方式实现这些方法。

所以我会首先实例化一个 TParent 的对象,检查它是什么类型,然后将其转换为正确的孩子。

但是,当我这样做并调用在子类中完全实现的抽象方法之一时,我得到一个 EAbstractError。

例如:

myHardware:=TParent.Create();

if myHardware.TypeA then
   myHardware:=TChildA(myHardware)
else
   myHardware:=TChildB(myHardware);

myHardware.SomeMehtod();

我假设我不能将父类转换为子类,并且可能有更好的方法来做到这一点。任何指针?

4

3 回答 3

5

您需要一个工厂方法来根据您使用的硬件类型返回正确的类...

function CreateHardware(isTypeA: Boolean): TParent;
begin
  if IsTypeA then Result := TChildA.Create
  else Result := TChildB.Create;
end;
...

var
  myHardware: TParent;
begin
  myHardware := CreateHardware(True);
  myHardwarde.SomeMethod;
end;

...或者您可以使用State 模式

这两种方法的共同点是您的 TParent 类不具备确定硬件类型的知识。该知识被转移到工厂方法、工厂方法的调用者、工厂本身或状态类中。

于 2009-03-25T13:23:45.247 回答
4

感谢 Binary Worrier 和 Mghie 在这种情况下为我指明了正确的方向。在最小化硬件初始化不是问题的情况下,Lieven 给出的答案将是更简单的方法。

pImpl 成语在 SO 的其他地方讨论

以下是我如何理解伪德尔福代码中的实现(注意我没有为此烦恼公共/私人区别):

class TParent 
  procedure SomeMethod(); abstract;
end;

class TChildA (TParent)
  procedure SomeMethod(); override;
end;

class TChildB (TParent)
  procedure SomeMethod(); override;
end;

class THardware
 HardwareSpecficMethods: TParent;
 procedure SomeMethod;
 constructor Create();

contrsuctor THardware.Create();
begin
 InitializeHardware();
 If Hardware.TypeA then
  HardwareSpecificMethods:=TChildA.Create()
 else
  HardwareSpecificMethods:=TChildB.Create();
end;

procedure THardware.SomeMethod();
begin
  HardwareSpecificMethods.SomeMethod();
end;
end; {class THardware}
于 2009-03-25T15:42:37.017 回答
3

你是对的,你不能也不应该从基类转换为派生类。

我假设您不想让 Child 对象重新运行 Parent 构造函数?

如果是这样的话 。. .

删除当前的父/子关系,您将只有一个硬件类。对于特定的 ChildA 和 ChildB 功能,创建一个新的继承模式,这样您就有一个 ISpecificHardwareTasks 接口或基类,以及两个派生类(SpecificA 和 SpecificB)。

当硬件构建它自己时,它知道它正在使用什么类型的硬件,然后它创建一个SpecificA或SpecificB的实例)。此实例是硬件专用的。

硬件公开了包装 ISpecificHardWareTasks 方法的方法(如果有意义,它甚至可以实现该接口)。

如果有必要,特定类可以引用 Hardware 类(尽管我不知道您是否可以访问构造函数中的 this 指针,但我的 Delphi 已经生锈了)

希望这些杂谈有所帮助。

于 2009-03-25T13:32:12.790 回答