2013-07-12 79 views
2

从抽象基类创建子类的最佳方法。从抽象基类创建子类的最佳方法

在我的项目中,我有这样的基类抽象和两个子类。

TbaseClass=class 
public 
    procedure Doit;virtual;abstract; 
    procedure Calculate;virtual;abstract; 


Tchild1class=class(TbaseClass) 
.. 
protected 
    procedure CalcArea;virtual; 
public 
    procedure Doit;override; 
    procedure Calculate;override; 


Tchild2class=class(Tchild1class) 
protected 
    procedure CalcArea;override; 

在我的buttonclick代码中,我以这种方式创建所需的childclass,并且正在工作。

..... 
var 
T:TBaseClass; 
begin 
    case OP of 
    1: T:=Tchild1class.Create; 
    2: T:=TChild2Class.Create; 
T.Doit; 
T.Calculate; 
end; 

我的问题是下一个。 我可以在我的基抽象类中创建一个构造函数创建过程,这取决于int参数生成所需的子类? 例如:

constructor TBaseClass.Create(OP:integer); 
begin 
inherited; 
case OP of 
    1: Tchild1class.Create; ///>>>??? 
    2: TChild2Class.Create; //>>>>??? 
end; 

这是可能的吗?

什么是最好的方法来做到这一点?

回答

10

不,这是不可能的。一旦构造函数开始运行,正在创建的对象的类就被修复了。一个对象不能改变它的类,即使在施工过程中也是如此。

您可以编写一个工厂函数,它接受整数参数并选择实例化哪个后代类。这将很像你提出的无效构造函数,就像独立函数或类方法而不是构造函数一样。

你也可以写,只是返回的功能,然后你也可以在以后实例化它,就像这样:

type 
    TBaseClassClass = class of TBaseClass; 

function GetDescendantClass(op: Integer): TBaseClassClass; 
begun 
    case op of 
    1: Result := TChild1Class; 
    2: Result := TChild2Class; 
    else Assert(False); 
    end; 
end; 

var 
    DescendantClass: TBaseClassClass; 

DescendantClass := GetDescendantClass (op); 
T := DescendantClass.Create; 
T.DoIt; 

使用该技术,它有时是有用的,使构造函数是虚拟的,但这不是要求。

+0

Thx为答案,但需要声明TBaseClassClass类型?函数GetDescendantClass不能直接返回TBaseClass ?. –

+1

我已经向你展示了它的声明;你不需要更多的东西来声明它。如果返回类型是'TBaseClass',那么你将有一个工厂函数,并且你需要返回一个*实例*,而当返回类型是'TBaseClassClass'时,你返回一个*类*并在稍后创建实例。 'TBaseClassClass'就是所谓的*元类* - 查看它。 –