有人說多此一舉嗎,接口引用只是個地址,沒必要手動設為nil。
OBJ2 := TC2.Create;
try
Intf1 := OBJ2;
Intf1.DO;
Finally
OBJ2.Free;
End;
結果可能還會出你的意料,還是非法地址訪問錯誤。為什麼?因為Delphi編譯器耍了個小聰明,它認為你忘記把這個地址引用置為nil了,所以你會自動給你加上,看來Delphi編譯器聰明過頭了J。
怎麼解決呢?
方法1,先把接口引用置為nil,再釋放對象。
Intf1 := nil;
OBJ2.Free;
方法2,把接口引用強制轉成指針類型再置為nil。
Pointer(Intf1) := nil;
此時相當於直接把地址清零,不會調用_IntfClear。
我傾向於使用第二種方法,這樣你就不用考慮先釋放誰的問題了。而且有些設計模式中你可能只持有接口引用,而且你也不知道引用的對象什麼時候釋放,此時就必須使用方法2。
例如考慮Composite模式。
TComposite = class(TComponent, I1)
Private
interList: TXContainer;//一個容器類,存放“葉子”的接口引用。
Public
Procedure Add (AIntf: I1);
function DO: Boolean;
End;
它應該釋放它的“葉子”嗎?顯然不是,那“葉子”是不是一定會晚於這個“合成對象”對象釋放呢?我想也不一定吧。如果強制這樣規定的話,就失去很多的靈活性。所以我們肯定想這些接口引用置nil時,不會和原對象發生什麼關系,以免對象被釋放後出非法地址訪問錯誤。考慮使用什麼容器呢?array?TList?TInterfaceList?
首先想到肯定是TInterfaceList了,因為我們是要容納的就是接口。但是對他進行Free時,它會把它所有容納的接口置為nil,這正是我們不想要的。或者我們可以在Free之前先把它存儲的接口引用轉為指針再置為nil。