我正在编写一些针对两个版本的非常相似的硬件的软件,直到我使用API来初始化硬件,我才知道我将会找到哪种类型。
因为硬件非常相似,我计划有一个父类(TParent),它有一些抽象方法(硬件不同),然后是两个子类(TChildA,TChildB),它们以硬件相关的方式实现这些方法
所以我首先要实例化一个TParent对象,检查它是什么样的,然后把它投给正确的孩子。
然而,当我这样做并调用在子类中完全实现的一个抽象方法时,我得到一个EAbstractError。
e.g:
myHardware:=TParent.Create();
if myHardware.TypeA then
myHardware:=TChildA(myHardware)
else
myHardware:=TChildB(myHardware);
myHardware.SomeMehtod();
我假设我不能将父类强制转换为子类,并且还有一种更好的方法可以做到这一点。有什么指针吗?
答案 0 :(得分: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 pattern。
这两种方法中的共同点是你的TParent类没有确定硬件类型的知识。知识转移到工厂方法,工厂方法的调用者,工厂本身或状态类。
答案 1 :(得分:4)
感谢Binary Worrier和Mghie在这个例子中指出了我正确的方向。在最小化硬件初始化不是问题的情况下,Lieven给出的答案将更容易。
讨论了pImpl习语elsewhere on SO
以下是我如何理解伪delphi代码中的实现(注意我没有为公共/私人区别而烦恼):
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}
答案 2 :(得分:3)
你是对的,你不能也不应该从基类转换为派生类。
我假设你不想让Child对象重新运行Parent构造函数?
如果是这样的话。 。
按原样删除父/子关系,您将只有一个硬件类。 对于特定的ChildA和ChildB功能,创建一个新的继承模式,以便您拥有一个ISpecificHardwareTasks接口或基类,以及两个派生类(SpecificA& SpecificB)。
当硬件构建它自己的时候,它就会知道它正在使用什么类型的硬件,然后创建一个SpecificA或SpecificB的实例。此实例对硬件是私有的。
硬件公开了包装ISpecificHardWareTasks方法的方法(如果有意义,它甚至可以实现该接口)。
特定类可以引用Hardware类,如果有必要的话(虽然我不知道你是否可以在构造函数中访问this指针,但是我的Delphi生锈了)
希望这些谣言有所帮助。