Wiz*_*ard 17 delphi oop object
我有这样的代码
name := 'Foo';
If name = 'Foo' then
result := TFoo.Create
else if name = 'Bar' then
result := TBar.Create
else if name = 'FooFoo' then
result := TFooFoo.Create;
Run Code Online (Sandbox Code Playgroud)
有办法吗?
result := $name.create
Run Code Online (Sandbox Code Playgroud)
或者某种基于变量值创建类的方法?
所有类都扩展了相同的基类.
Rob*_*ove 28
从Delphi 2010开始,增强的RTTI允许您在不必创建自己的类注册表的情况下执行此操作.
使用该RTTI
单元,您可以使用多种选项.
对于参数较少的构造函数,最简单的一个是.
var
C : TRttiContext;
O : TObject;
begin
O := (C.FindType('UnitName.TClassName') as TRttiInstanceType).MetaClassType.Create;
...
end;
Run Code Online (Sandbox Code Playgroud)
以下是使用.传递参数的示例 TRttiMethod.Invoke()
var
C : TRttiContext;
T : TRttiInstanceType;
V : TValue;
begin
T := (C.FindType('StdCtrls.TButton') as TRttiInstanceType);
V := T.GetMethod('Create').Invoke(T.metaClassType,[self]);
(V.AsObject as TWinControl).Parent := self;
end;
Run Code Online (Sandbox Code Playgroud)
我在该单元上写了几篇文章,RTTI
因为有很多选择.
根据David请求更新:
使用类型(虚拟构造函数)比较使用构造的用法 TRttiType.Invoke
我个人认为每个都有不同的用途.如果我知道前面的所有类型,我使用类类型方法.
RRU*_*RUZ 16
您可以使用该GetClass
函数,但必须先使用RegisterClass
或RegisterClasses
方法注册类.
GetClass(const AClassName: string): TPersistentClass;
Run Code Online (Sandbox Code Playgroud)
Dav*_*nan 10
执行此操作的常规方法是使用虚拟构造函数.一个很好的例子是TComponent
你无疑熟悉的.
TComponent
有以下构造函数:
constructor Create(AOwner: TComponent); virtual;
Run Code Online (Sandbox Code Playgroud)
另一个关键TComponentClass
是声明为class of TComponent
.
当VCL流式传输.dfm文件时,它会从.dfm文件中读取该类的名称,并且通过我们不需要在此处覆盖的某个过程,将该名称转换为变量,ComponentClass
例如类型TComponentClass
.然后它可以用以下实例化对象:
Component := ComponentClass.Create(Owner);
Run Code Online (Sandbox Code Playgroud)
这是拥有虚拟构造函数的一大优势,我鼓励您采用相同的方法.
如果必须使用字符串来标识类,那么您仍然需要提供一个查找例程来将字符串类名转换为类引用.如果方便的话,您可以挂钩到使用的相同VCL机制TComponent
,即RegisterClass
.
或者,如果您可以name
使用类引用替换代码,那么您可以编写:
type
TFoo = class
constructor Create; virtual;
end;
TBar = class(TFoo);
TFooClass = class of TFoo;
var
MyClass: TFooClass;
...
MyClass := TFoo;
result := MyClass.Create;//creates a TFoo;
MyClass := TBar;
result := MyClass.Create;//creates a TBar;
Run Code Online (Sandbox Code Playgroud)