2016/08/26

Delphi 免寫 FreeAndNil 的方法

好的 Free 帶你上天堂 (咦?) 圖片來源


最近看到一篇關於葡萄牙人寫的文章:FreeAndNil... Esqueça

內文是說明在物件導向的時代,JAVA、C# 這類的語言都有垃圾自動回收機制,進化中的 Delphi 其實也有。

接著便開始說明了使用 FreeAndNil 讓我們的原始碼非常噁心的經過。


提出的解法是使用 Interface!


原先我們的寫法可能是:







還是先來說說 Interface 的結構好了

以 Help 的 Interface 範例來看:
  IMyInterface = interface
    procedure P1;
    procedure P2;
  end;

  TMyImplClass = class
    procedure P1;
    procedure P2;
  end;

  TMyClass = class(TInterfacedObject, IMyInterface)
    FMyImplClass: TMyImplClass;
    property MyImplClass: TMyImplClass read FMyImplClass
      implements IMyInterface;
  end;


實戰時我們程式大概會這樣寫:
var
  MyClass: TMyClass;
  MyInterface: IMyInterface;
begin
  MyClass := TMyClass.Create;
  MyClass.FMyImplClass := TMyImplClass.Create;
  MyInterface := MyClass;
  MyInterface.P1; // calls TMyClass.MyP1;
  MyInterface.P2; // calls TImplClass.P2;


然後就

























得到 Memory Leak!!!
眼睛業障有點重 (笑)


其實,我們只要這樣寫就可以了:
var
  MyInterface: IMyInterface;
begin
  MyInterface :=  TMyClass.Create;
  MyInterface.P1;
  MyInterface.P2;


然而,葡萄牙的這位作者提供了一種介面靜態實作的觀點,簡化寫法如下:
  TMyTestClass = class(TInterfacedObject, IMyInterface)
    constructor Create();
    class function New: IMyInterface;
    procedure P1;
    procedure P2;
  end;
//呼叫時寫法如下:
  TMyTestClass.New.P1;
  TMyTestClass.New.P2;



一切真是太美好啦~~~~















BUT!人生最厲害的就是這個 BUT!

不知道你有沒有使用過 IOUtils 單元;
TPath、TDirectory、TFile三個物件都是採用 Record 宣告,實際寫法類似:

TPath.GetHomePath

這種使用方式也很方便,一樣不需要做釋放處理。

我們來寫寫看上述的範例使用 Record 的寫法:
  TMyTestRecord = record
    class procedure P1;static;
    class procedure P2;static;
  end;
//呼叫時寫法如下:
  TMyTestRecord.P1;
  TMyTestRecord.P2;


這種範例場合,似乎是 Record 比較簡單使用呢!


1. 以上就是整理拋棄 FreeAndNil 的方式,您是否有其它的看法呢?歡迎在文末留言!


2. 關於 Interface 的應用上,這位葡萄牙作者的部落格內容非常充實,有興趣深造的可以參考文末的連結。



See also:

沒有留言:

張貼留言