2011-07-11 56 views
7

這可能是一個簡單的問題,但我想知道如何確保調用類的構造函數。德爾福 - 確保調用類構造函數

如果我有以下代碼:

type TMyObject = class(TObject) 
    public 
    constructor Create;override; 
end; 

implementation 

constructor TMyObject.Create;override; 
begin 
    inherited; 
    //do other instantiation 
end; 

德爾福不允許這樣 - 「不能覆蓋靜態方法」。

我想要做的是確保該對象是使用我的自定義Create構造函數創建的,並禁止調用祖先創建構造函數。

我目前的解決問題的方法是定義像這樣一個獨特的signatured創建構造函數:

constructor Create(aName : String);overload; 

但程序員可能調用祖先Create()方法。

+0

感謝您的答案,有沒有創建任何原因是靜態方法,但Destroy是虛擬的?什麼是優先的方式 - 使用AfterConstruction,或創建? – Simon

+0

你可能想問一個關於這個問題的另一個問題,因爲在評論中回答「太多」了...... –

+0

無論如何我會試一試 - 除了創建一個任意類的對象之外,它更有可能在任意類上調用析構函數(例如'帶有'OwnsObject:= True'的TObjectList')。 –

回答

14

您只需重新引入一個帶有祖先名稱的構造函數。一旦你這樣做了,用戶就無法創建調用TObject中介紹的構造函數的TMyObject。如果使用這樣的代碼:

TMyObject = class 
public 
    constructor Create; 
end; 

constructor TMyObject.Create; 
begin 
    // I am not calling the inherited constructor because 
    // I do not want to. 
end; 

因爲祖先的構造函數不是虛擬的,您不使用override修改器TMyObject.Create

使用此方案,用戶不可能使用在祖先中引入的構造函數來創建TMyObject。在這種情況下,祖先是TObject,它唯一的構造函數是TObject.Create。如果用戶寫這段代碼:

X := TMyObject.Create; 

這是相當明顯的,TMyObject的構造函數被調用,而不是一個在TObject介紹。


如果你害怕用戶會通過箍,以創建類使用祖先的構造跳,你可以從AfterConstruction方法做你的東西。這是一個虛擬的方法,所以即使你的對象是使用一個祖先的類型的類引用創建它被調用:

TMyObject = class 
public 
    procedure AfterConstruction;override; 
end; 
+0

打我幾秒鐘! –

+0

該死的,我想我讀得太多了,因爲它太簡單了! – Simon

+1

用於AfterConstruction。甚至不知道這是可用的。 – Simon

6

TObject.Create不是虛擬的構造函數,因此錯誤。

「其他程序員」可以稱爲祖先創建方法的唯一方法是故意跳過一些箍來做到這一點,例如,

var 
    ClassRef: TClass; 
    Obj : TObject; 
begin 
    ClassRef := TMyObject; 
    Obj := ClassRef.Create; 
end; 

爲新引進的構造函數將隱藏非虛擬TObject.Create

你想要什麼可能是更喜歡:

type TMyObject = class(TObject) 
    public 
    constructor Create;virtual; 
end; 

implementation 

constructor TMyObject.Create; 
begin 
    inherited; 
    //do other instantiation 
end; 
+0

+1用於使用祖先類型的類類型變量實例化類。 –

+0

這看起來不對。在實現部分忽略「覆蓋」。 –

+0

@Rudy - 很好看。固定! –