2017-05-30 44 views
3

我已經讀過,接口是一個好東西decopule的代碼和尼克霍奇斯寫了一個很好的篇章。讀取我已經產生的代碼:德爾福接口和類變量類型

//interfaces 
type 
ILocalization = interface 
    ['{1D144BCE-7D79-4672-8FB5-235422F712EE}'] 
    function localize(const aWordId: string): string; 
end; 

type 
IActions = interface 
    ['{31E8B24F-0B17-41BC-A9E4-F93A8E7F6ECF}'] 
    procedure addWord(const aIndex, aWord: string); 
    procedure removeWord(const aIndex: string); 
end; 

//implementation 
type 
TLocalization = class sealed (TInterfacedObject, ILocalization, IActions) 
    private 
    FTranslationList: TDictionary<string, string>; 
    public 
    constructor Create; 
    destructor Destroy; override; 
    //interface implementations 
    function localize(const aWordId: string): string; 
    procedure addWord(const aIndex, aWord: string); 
    procedure removeWord(const aIndex: string); 
end; 

我打算使用這個類來本地化(翻譯)我的delphi android應用程序。


當我打算創建一個類的實例時,我執行以下操作。

var 
Italiano: TLocalization; 
begin 
Italiano := TLocalization.Create; 
end; 

由於TLocalization應該繼承AddRef和Release我不會嘗試最後這一點,但是這確實發生,即使意大利語是類類型,而不是一個接口類型?

  • 意大利語:

    我的意思,這是TLocalization - >我在這裏可以使用所有的方法

  • 意大利語:ILocalization - 在這裏>我只能使用本地化功能

考慮到(正如我已經說過的),TLocalization繼承了AddRef和Release,如果我理解正確,我不必釋放它。它應該與ILocalization一樣,但它有其他好處嗎?我不明白以上兩種情況有什麼區別

回答

5
var 
    Italiano: TLocalization; 
begin 
    Italiano := TLocalization.Create; 
    // do stuff 
end; 

這會讓你面對混合不同生命週期模型的缺陷。如代碼所示,AddRef尚未被調用,因此引用計數爲0.因此,您將泄漏此對象。

所以,你可能會改變代碼:

var 
    Italiano: TLocalization; 
begin 
    Italiano := TLocalization.Create; 
    try 
    // do stuff 
    finally 
    Italiano.Free; 
    end; 
end; 

現在你不漏。

太好了。但是如果你確實參考了會發生什麼?

var 
    Italiano: TLocalization; 
    Localization: ILocalization; 
begin 
    Italiano := TLocalization.Create; 
    try 
    Localization := Italiano as ILocalization; 
    // do stuff 
    finally 
    Italiano.Free; 
    end; 
end; 

現在,當你分配到LocalizationAddRef被調用。因此引用計數變爲1.當Localization超出範圍時,Release被調用,並且引用計數返回到0並且實例被銷燬。不幸的是,你也明確地摧毀它。對象需要被銷燬一次。

遵循的最乾淨和最簡單的規則不是混合使用壽命模型。如果您通過引用計數進行生命週期管理,那麼只能這樣做。確保在創建對象時始終引用對象,並讓編譯器生成引用計數代碼來管理生命週期。

確保遵循該規則的一種方法是確保您只能通過接口引用訪問該對象。像這樣:

var 
    Italiano: ILocalization; 
begin 
    Italiano := TLocalization.Create; 
    // do stuff 
end; 
+0

好吧我想現在我明白了。所以我們來看看你寫的最後一段代碼。如果3種方法addWord,removeWord和localize都是在ILocalization裏面,我可以完全使用我的課程。但到目前爲止,我不能這樣做,因爲ILocalization只爲本地化方法提供了refCount,而不是其他方法,所以我不能調用其他方法。我是否正確? –

+0

否。對象實現了兩個接口,而對象擁有引用計數,而不是接口。所以如果你想訪問其他方法,使用'var Actions:IActions; ....行動:=意大利語爲IActions;'。現在你有兩個接口變量,後面是相同的單個對象,現在有一個引用計數爲2. –

+0

好吧,所以我可以在終極使用「正常方式」的類,或者我必須做一個類型轉換安全使用IActions或ILocalizations。 –