delphi中父类和子类之间的转换

发布于 2024-07-15 04:58:00 字数 528 浏览 5 评论 0原文

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

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

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

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

例如:

myHardware:=TParent.Create();

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

myHardware.SomeMehtod();

我假设我无法将父类转换为子类,而且可能有更好的方法来做到这一点。 有什么指点吗?

I'm writing some software that targets two versions of very similar hardware which, until I use the API to initialize the hardware I'm not able to know which type I'll be getting back.

Because the hardware is very similar I planned to have a parent class (TParent) that has some abstract methods (for where the hardware differs) and then two child classes (TChildA, TChildB) which implement those methods in a hardware dependent manner.

So I would first instantiate an object of TParent check what kind it is then cast it to the correct child.

However when I do this and call one of the abstract methods fully implemented in the child class I get an EAbstractError.

e.g:

myHardware:=TParent.Create();

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

myHardware.SomeMehtod();

I'm assuming that I can't cast a Parent Class to a child class, and also that there's probably a better way of doing this. Any pointers?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

涙—继续流 2024-07-22 04:58:00

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

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;

...或者您可以使用 状态模式

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

You need a factory method to return you the correct class depending on the Type of hardware you are using...

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;

... or you could use the State pattern.

Common in either approach is that your TParent class does not has the knowledge to determine the type of hardware.That knowlegde is transfered into the factory method, caller of the factory method, factory itself or state class.

撩起发的微风 2024-07-22 04:58:00

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

pImpl 惯用法在 SO 的其他地方进行了讨论

以下是我如何理解伪实现: delphi-code(请注意,我没有为此担心公共/私人区别):

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}

Thanks to Binary Worrier and Mghie for pointing me in the right direction in this instance. The answer given by Lieven would be the easier way in cases where minimising the initialization of the hardware wasn't an issue.

The pImpl idiom is discussed elsewhere on SO

Here is how I understand the implementation in pseudo-delphi-code (note I've not bothered with public/private distinctions for this):

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}
小巷里的女流氓 2024-07-22 04:58:00

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

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

如果是这样 。 。 。

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

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

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

如果有必要,特定类可以引用 Hardware 类(尽管我不知道您是否可以在构造函数中访问 this 指针,我的 Delphi 正在变得生疏)

希望这些漫谈能有所帮助。

You're right, you can't and shouldn't cast from base class to derived class.

I'm assuming you don't want to have the Child object re-run the Parent constructor?

If so . . .

Remove the Parent/Child relationship as it stands, you will have only one Hardware class.
For the specific ChildA and ChildB functionality, create a new inheritance pattern, so that you have an ISpecificHardwareTasks interface or base class, and two derived classes (SpecificA & SpecificB).

When Hardware is constructing it's self, and it gets to the point where it knows what type of hardware it's working with, it then creates an instance of SpecificA or SpecificB). This instance is private to Hardware.

Hardware exposes methods which wrap the ISpecificHardWareTasks methods (it can even implement that interface if that makes sense).

The Specific classes can take a reference to the Hardware class, if that's necessary (though I don't know if you have access to the this pointer in a constructor, my Delphi is getting rusty)

Hope these ramblings helped somewhat.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文