Delphi接口继承和观察者模式

发布于 2024-10-27 22:58:57 字数 1333 浏览 1 评论 0原文

我想创建一个通用的主题接口,然后将其与“具体”观察者类一起重用。所以我为主题尝试了这段代码:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

单身狗的梦 2024-11-03 22:58:57

您需要使用 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 write Obs as ISerialObserver. But why not make your list TList<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 the is operator, or the rather more functional Supports() function.

Also, you don't need to inherit from IInterface, that is implicit. So you can replace ISubject = interface(IInterface) with ISubject = interface and so on.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文