2009-02-09 18 views
4

我不知道OWNER对象类的名称。所以我必须检查我的代码中的任何地方:检查类名

if TObject(OWNER) is TFirstClass then begin 
    TFirstClass(OWNER).FirstFunction; 
    TFirstClass(OWNER).SecondFunction; 
    ... 
end else 
if TObject(OWNER) is TSecondClass then begin 
    TSecondClass(OWNER).FirstFunction; 
    TSecondClass(OWNER).SecondFunction; 
    ... 
end; 

有没有更好的方法?因为如果条件在代码的许多地方我必须这样做。 TFirstClass和TSecondClass(我必须运行)的所有功能都是相同的。

注:我使用Delphi 5.

+0

你是否控制了业主? (你能改变班级的定义吗?) – 2009-02-09 16:29:26

+0

OWNER是什么类型。当你对TObject进行类型转换时,我假设指针或整数/红衣主教? – 2009-02-09 21:21:57

回答

12

如果你有TFirstClass和TSecondClass用不上,但还是要简化代码,这里有一个办法:

创建一个适配器的基类:

type 
    TMyAdapter = class(TObject) 
    public 
    procedure FirstMethod; virtual; abstract; 
    procedure SecondMethod; virtual; abstract; 
    end; 

然后创建一个子类TFirstClassAdapter和TSecondClassAdapter并分别为它们分别提供TFirstClass或TSecondClass的实例的私有引用。添加一个设置此引用的构造函数。覆盖适配器类的方法,以便它们调用适配的类。

type 
    TFirstClassAdapter = class(TMyAdapter) 
    private 
    fObject: TFirstClass; 
    public 
    constructor Create(AAdaptedObject: TFirstClass); 

    procedure FirstMethod; override; 
    procedure SecondMethod; override; 
    end; 

constructor TFirstClassAdapter.Create(AAdaptedObject: TFirstClass); 
begin 
    inherited Create; 
    fObject := AAdaptedObject; 
end; 

procedure TFirstClassAdapter.FirstMethod; 
begin 
    fObject.FirstMethod; 
end; 

procedure TFirstClassAdapter.SecondMethod; 
begin 
    fObject.SecondMethod; 
end; 

与其他班级相同。现在你只需要决定是否创建一次适配器并传递它,或者你是否创建了一个你需要的地方调用的函数,以及哪个函数会为你的具体类提供一个适配器。

如果您使用接口实现适配器,那么您甚至不需要自己管理适配器的生存期。

通过这种方式,您可以获得Ulrich在his answer中给出的多态行为,但无需更改TFirstClass和TSecondClass。

11

派生TFirstClass和TSecondClass从声明虚拟方法了firstFunction和SecondFunction一个共同的基类。

Uli。

-1

起初我对我英语不好。
如果在响应(适配器和派生自基类)之前不能执行2,则可以使用RTTI按名称访问过程。

该过程必须在已发布部分中声明。

如果你已经像这样的声明:

TFirstClass = class(TObject) 
    published 
    procedure FirstFunction; 
    procedure SecondFunction; 
    end; 
    TSecondClass = class(TObject) 
    published 
    procedure FirstFunction; 
    procedure SecondFunction; 
    end 

你可以做这样的事情,如果你有名称来执行方法:

// Acceso a la rutina; TObject is a Base class for 
    // TFirstClass and TSecondClass 
    Routine.Data := Pointer(obj as TObject); 
    // Devuelve la dirección de un método published; Method for it's name 
    Routine.Code := (obj as TObject).MethodAddress('SecondFunction'); 
    // Not find 
    if (Routine.Code = nil) then Exit; 
    // execute 
    TExecuteMethod(Routine); 

你可以在这里看到类似的代码:
* Tip4 * Tip7

问候。