首先,大家好,感谢您的帮助。
我尝试使用Interfaces在Delphi中实现Observer模式,因此Object可以同时成为Subject和Observer。
我有一个实现ISubject的类,使用以下方法:
procedure TSomeClass.Attach(const observer: IObserver);
var
I: Integer;
begin
if Fobservers = nil then
begin
Fobservers := TInterfaceList.Create;
end;
if Fobservers.IndexOf(Observer) < 0 then
Fobservers.Add(Observer);
end;
我跟随乔安娜卡特在http://blogs.teamb.com/joannacarter/2004/06/30/690的例子。
在应用程序中,我实例化一个实现IObserver的对象,并将它附加到TSomeClass对象(它也实现了ISubject)。
然后我从TSomeClass对象调用Notify方法,它可以正常工作。当我尝试FreeAndNil我的Observer对象时,我的问题出现了,因为我得到了一个无效的指针操作,即使我使用了&#39; const&#39;在参数中,当我在调试模式下到达FreeAndNil行时,正确分配了对象,并在通知中设置了所有属性并更改了随机属性。
我注意到,当我打电话给这条线路时,我无法释放我的物体:
Fobservers.Add(Observer);
如果我评论这一行,那么我可以释放我的对象。应用程序中的代码如下所示:
procedure TfrmAlisson.Button2Click(Sender: TObject);
var
locSomeClass: TSomeClass;
locObserver: TSomeObserverClass;
I: Integer;
begin
locObserver:= TSomeObserverClass.create(394693);
try
locSomeClass:= TSomeClass.create(263151);
try
locSomeClass.Attach(locObserver);
locSomeClass.NotifyObservers;
finally
FreeAndNil(locSomeClass);
end;
ShowMessage(IntToStr(locObserver.SomeProperty)); // This property is changed inside the notify
finally
locObserver.Free; // error
end;
end;
我想知道为什么将IObserver添加到TInterfaceList会导致这种情况(我使用Delphi 2009)。
答案 0 :(得分:3)
您的TSomeObserverClass
很可能是继承自TInterfacedObject
。
当您在Attach
中传递它时,它会以IObserver
传递,这就是引用计数开始的位置。当RefCount添加到Fobservers
时,它会变为1销毁locSomeClass
并使用Fobservers
列表再次删除它会导致RefCount降至0.然后,IObserver
接口引用后面的实例将被销毁。
这里显示的问题是重现它的最小代码:
var
obj: TInterfacedObject;
list: TInterfaceList;
begin
o := TInterfacedObject.Create;
try
list := TInterfaceList.Create;
list.Add(o);
list.Free;
finally
FreeAndNil(o);
end;
end;
如果执行此操作,您会在FreeAndNil中看到EInvalidError,因为该实例已被TInterfacedObject
中实现的自动引用计数破坏。
如前所述,您不应混合对象和接口引用或继承自未实现自动引用计数的类。