2012-01-29 101 views
2

我有一个主类和实现的方法具有相同名称的多个继承的类,如:Delphi的对象铸造

MainClass = class(TImage) 
    //main class methods... 
end; 

MyClass1 = class(MainClass) 
    procedure DoSomething; 
end; 

MyClass2 = class(MainClass) 
    procedure DoSomething; 
end; 

MyClass3 = class(MainClass) 
    procedure DoSomething; 
end; 

我也有包含指向对象实例(几类)一个从TList。 如果我想为每个班级拨打正确的DoSomething程序,我是否使用以下内容?

if TList[i] is MyClass1 then 
    MyClass1(TList[i]).DoSomething 
else if TList[i] is MyClass2 then 
    MyClass2(TList[i]).DoSomething 
else if TList[i] is MyClass3 then 
    MyClass3(TList[i]).DoSomething 

是否有一些铸造方法,允许我在几行代码中执行此操作?

回答

10

是,虚拟多态性:)

MainClass = class(TImage) 
    procedure DoSomething; virtual; 
end; 

MyClass1 = class(MainClass) 
    procedure DoSomething; override; 
end; 

MyClass2 = class(MainClass) 
    procedure DoSomething; override; 
end; 

MyClass3 = class(MainClass) 
    procedure DoSomething; override; 
end; 

然后就是:

if TList[i] is MainClass then 
    MainClass(TList[i]).DoSomething 

如果你不想做一个空MainClass.DoSomething过程中,你也可以将其标记virtual; abstract;

+1

多态性没有继承......要具体 – GDF 2012-01-31 19:46:39

+0

@GDF,真实,编辑。 – 2012-01-31 19:48:05

+0

真正的多态还是虚拟的? ;) – mjn 2012-02-01 16:09:21

4

虚拟继承的答案对于您描述的类从一个公共基类下降的情况来说是最好的,但是如果您遇到了类之间没有公共基类并且需要这种行为的情况,那么您可以使用接口,而不是实现相同的结果:

IMainInterface = interface 
    ['{0E0624C7-85F5-40AF-ADAC-73B7D79C264E}'] 
    procedure DoSomething; 
    end; 

    MyClass = class(TInterfacedObject, IMainInterface) 
    procedure DoSomething; 
    destructor Destroy; override; 
    end; 

    MyClass2 = class(TInterfacedObject, IMainInterface) 
    procedure DoSomething; 
    end; 

    MyClass3 = class(TInterfacedObject, IMainInterface) 
    procedure DoSomething; 
    end; 

,然后使用它会是这个样子:

var 
    i: integer; 
    list: TInterfaceList; 
    main: IMainInterface; 
begin 
    list := TInterfaceList.Create; 

    list.Add(MyClass.create); 
    list.Add(MyClass2.Create); 
    list.Add(MyClass3.Create); 

    for i := 0 to 2 do 
    if Supports(list[i], IMainInterface, main) then 
     main.DoSomething; 

    list.Free; 
+2

'Supports()'已经重载了返回接口指针的版本(如果找到的话),所以你不必调用'as'运算符,这将会冗余地再次调用相同的接口查找。 – 2012-01-30 06:03:46

+0

谢谢,因为我弄糟了接口,所以太久了。我已根据您的建议对其进行了修改。 – 2012-01-30 13:04:16

+0

您可以将列表声明为IInterfaceList,这将添加引用计数并保存列表。免费(如果将它保留为TInterfaceList,请不要忘记使用try ..来保护它) – mjn 2012-02-01 16:08:29