2012-01-29 114 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