2009-11-21 102 views
5

我有一個類,我們稱之爲TMyObject,它應該返回一個稍微修改後的副本。 因此,其功能之一應返回相同類型的對象本身:我可以創建與自身類型相同的對象嗎?

function TMyObject.TrimEnds: TMyObject; 
begin 
    Result:= TMyObject.Create; 
    Result.DoStuff; 
edn; 

我能做到這一點?這是合法的,我在做什麼?

我的意思是,我已經試過了,編譯器允許我這樣做,但我想知道是否會有很長時間/隱藏的負面影響。

任何想法將不勝感激。 謝謝。


編輯: 新的稍作修改的副本將被保存到磁盤。這是某種'另存爲...'。 工作原理:原始對象創建自身副本,指示該副本進行一些更改並保存到磁盤。然後原件釋放副本。這樣我保持原始對象在內存中不變,但我有這個修改版本的磁盤。

你可能會認爲我的對象擁有一張圖片。我需要的是一個函數,返回一個稍微修改後的圖片副本。

回答

5

但我不知道是否會有長時間的 時間/隱藏的負面影響。

我沒有看到任何東西,而且我用我自己的鏈表來做這件事,從來沒有任何問題。我認爲這與在任何其他地方創建實例幾乎一樣。

+0

大。 非常感謝大家。 – Ampere

+0

確保你釋放資源。否則,你的對象留在內存中,永遠不會釋放。那麼,在程序終止時就是這樣。 – Scoregraphic

1

你寫的東西絕對沒有錯。你只是返回一個對象,這是完全有效的,它可以是任何其他類型的任何其他對象。

2

我想你是對的,這段代碼對我來說似乎不對。 你總是要說清楚誰是負責釋放你回來的對象。 在大多數情況下,該對象不會被釋放。

更好的方法是通常讓調用者創建對象,將其傳遞給您的方法(您只需要一個過程),然後修改它。

我很想知道爲什麼你想要返回一個「稍微修改過的版本」的對象。這聽起來反直覺...

+0

請看我原來的帖子。我增加了更多解釋。 – Ampere

2

正如其他人所說,沒有什麼錯,但可能有更好的辦法。

變體1:將其更改爲類方法並給它一個有意義的名稱。

class function TMyObject.CreateSpecialized: TMyObject; 
begin 
    Result := TMyObject.Create; 
    //initialize Result 
end; 

anObj := TMyObject.CreateSpecialized; 

變體2:使用構造函數。你可以在一個類中有多個構造函數。

constructor TMyObject.CreateSpecialized; 
begin 
    Create; // make sure everything is initialized correctly 
    // now do custom initialization 
end; 

anObj := TMyObject.CreateSpecialized; 

這兩個示例中的用法都是相同的,但在第二種情況下,您的意圖對隨機閱讀器更清晰。

如果您想要取一個對象並根據第一個對象的字段創建另一個對象,請使用帶參數的構造函數。

constructor TMyObject.CreateSpecialized(obj: TMyObject); 
begin 
    Create; 
    intField := obj.IntField * 2; 
end; 

anObj := TMyObject.CreateSpecialized(otherObj); 
+0

+1類方法 – RRUZ

+0

有一個傳統叫你最後一個例子是「拷貝構造函數」 –

+0

@PA:不,因爲拷貝構造函數會創建一個相同的*拷貝*,而不是一個變種。 Delphi中複製構造函數沒有太多用處。由於所有對象只能通過引用訪問,因此很少需要它們。 – mghie

2

如果從TMyObject衍生像TMyOtherObject = class(TMyObject)一個新的類,在TrimEnds功能仍然會返回一個TMyObject代替TMyOtherObject的正如人們所預料。

您可以使用此方案解決這個問題:

TMyObjectClass = class of TMyObject; 

function TMyObject.TrimEnds: TMyObject; 
begin 
    Result:= TMyObjectClass(ClassType).Create; 
    Result.DoStuff; 
end; 
+0

這不需要創建虛擬? – gabr

+0

@gabr:僅當派生類具有其自己的創建時。在這種情況下,基礎Create必須是虛擬的,並且派生必須覆蓋它。 ClassType的使用只保證正確的類被實例化 - 用戶必須注意正確的Create被調用。 –

+0

構造函數需要聲明爲虛擬的,否則構造函數代碼將不會被執行:http://stackoverflow.com/questions/791069/ – mjn

相關問題