Delphi接口继承和观察者模式
我想创建一个通用的主题接口,然后将其与“具体”观察者类一起重用。所以我为主题尝试了这段代码:
unit uISubject;
interface
type
ISubject = interface(IInterface)
procedure RegisterObserver(Observer: IInterface);
procedure RemoveObserver(Observer: IInterface);
procedure NotifyObservers;
end;
implementation
end.
我有以下观察者类:
用于串行通信的观察者
unit uISerialObserver;
interface
type
ISerialObserver = interface(IInterface)
['{EF833BD7-31C1-49B3-8041-F1574AC043F0}']
procedure DataAvailable(ReceivedData: AnsiString);
end;
implementation
end.
更新进度栏的观察者
unit uIProgressObserver;
interface
type
IProgressObserver = interface(IInterface)
['{05AC7C76-CD41-42AB-B793-1512E68D91D5}']
procedure UpdateProgressParameters(Min, Max: Cardinal);
procedure IncrementParameter;
end;
implementation
end.
我已经实现了这样的通知方法:
procedure TSerialPortCommunicator.NotifyObservers;
var
Obs: IInterface;
begin
for Obs in FObservers do
begin
ISerialObserver(Obs).UpdateObserver(FReceivedData);
end;
end;
where
FObservers: TList<IInterface>;
When NotifyObservers
运行时,Delphi 返回访问冲突错误。
我想知道我做错了什么?
I'd like to create a generic Subject Interface and so reuse it with "specifics" Observer classes. So I tried this code for the Subject:
unit uISubject;
interface
type
ISubject = interface(IInterface)
procedure RegisterObserver(Observer: IInterface);
procedure RemoveObserver(Observer: IInterface);
procedure NotifyObservers;
end;
implementation
end.
And I have the following classes for Observers:
An Observer for serial communication
unit uISerialObserver;
interface
type
ISerialObserver = interface(IInterface)
['{EF833BD7-31C1-49B3-8041-F1574AC043F0}']
procedure DataAvailable(ReceivedData: AnsiString);
end;
implementation
end.
An Observer that update Progress bar
unit uIProgressObserver;
interface
type
IProgressObserver = interface(IInterface)
['{05AC7C76-CD41-42AB-B793-1512E68D91D5}']
procedure UpdateProgressParameters(Min, Max: Cardinal);
procedure IncrementParameter;
end;
implementation
end.
And I've implemented the Notify method like this:
procedure TSerialPortCommunicator.NotifyObservers;
var
Obs: IInterface;
begin
for Obs in FObservers do
begin
ISerialObserver(Obs).UpdateObserver(FReceivedData);
end;
end;
where
FObservers: TList<IInterface>;
When NotifyObservers
runs, Delphi returns an Access Violation Error.
I'd like to know what I'm doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要使用
as
运算符通过动态转换来转换接口。您的代码
ISerialObserver(IInterface(Obs))
是某个故障点。您应该将Obs 写为 ISerialObserver
。但为什么不创建列表TList
从而避免强制转换呢?也就是说,您确定列表中的所有内容都实现了 ISerialObserver 吗?从这些摘录中并不明显。您可以使用
is
运算符或功能更强大的Supports()
函数检查接口支持。另外,您不需要从 IInterface 继承,这是隐式的。因此,您可以将
ISubject = interface(IInterface)
替换为ISubject = interface
等等。You need to cast the interface with a dynamic cast using the
as
operator.Your code,
ISerialObserver(IInterface(Obs))
, is a certain point of failure. You should instead writeObs as ISerialObserver
. But why not make your listTList<ISerialObserver>
and thus avoid the cast?That said, are you sure everything in your list implements
ISerialObserver
? It's not obvious from these excerpts. You can check for interface support with theis
operator, or the rather more functionalSupports()
function.Also, you don't need to inherit from IInterface, that is implicit. So you can replace
ISubject = interface(IInterface)
withISubject = interface
and so on.