You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ada多态回调问题:Observer模式中访问子程序类型不匹配

Ada Observer模式中访问子程序类型不匹配问题

尝试使用OOP和动态调度实现Observer模式时,遇到无法创建访问子程序常量的问题:命名访问类型的参数与类型扩展的过程参数不匹配。以下是最小复现示例(省略订阅逻辑):

Alarms包定义

package Alarms is

  type time_t is mod 2**32;

  type AlarmObserver_t is interface;
  type Callback_t is access procedure (this : in out AlarmObserver_t);

  type AlarmPublisher_t (<>) is tagged limited private;
  function fConstructor (capacity : in Positive) return AlarmPublisher_t;

private

  type AlarObserverAcc_t is access AlarmObserver_t'Class;

  type dummy_t is new AlarmObserver_t with null record;
  procedure pEventDummy (this : in out dummy_t) is Null;

  dummy : constant AlarObserverAcc_t := new dummy_t;
  dummyCallback : constant Callback_t := pEventDummy'Access; -- *此处编译失败*

  type Node_t is limited
    record
      Observer : AlarObserverAcc_t := dummy;
      Callback : Callback_t := dummyCallback;
      time : time_t := time_t'Last;
    end record;

  defaultNode : constant Node_t := Node_t' (Observer => dummy,
                                            Callback => dummyCallback,
                                            time     => time_t'Last);

  type ObserverArray_t is array (Positive range <>) of Node_t;

  type AlarmPublisher_t (capacity : Positive) is tagged limited 
    record
      -- 成员"observers"拥有默认初始化,因为Node_t已初始化
      observers : ObserverArray_t (Positive'First .. capacity);
    end record;

end Alarms;

Alarms包体实现

package body Alarms is
  
  function fConstructor (capacity : in Positive) return AlarmPublisher_t is
  begin
    return Obj : AlarmPublisher_t (capacity => capacity) do
      Null;
    end return;
  end fConstructor;

end Alarms;

参考过Matthew Heaney的回调式Observer模式实现,他使用了类范围参数的访问子程序,但我希望采用OOP语法,让具体观察者将这些过程作为原语实现。

疑问

为什么dummy_t实现了AlarmObserver_t接口,但pEventDummy却无法与Callback_t兼容?能否实现我的预期需求?

预期需求

希望具体观察者能灵活订阅告警到期时想要接收通知的方法,无需预先将所有可能的方法定义为AlarmObserver_t接口的抽象原语,而是让具体观察者订阅对应的访问子程序,在不同时机接收通知。示例如下:

ConcreteObserver包示例

with Alarms;

package ConcreteObserver is

  type ConcreteObserver_t is new Alarms.AlarmObserver_t with private;

  -- 告警到期时接收通知的evTimeout过程
  -- 空实现用于编译
  procedure evTimeout (this : in out ConcreteObserver_t) is null;

  -- 另一种告警到期时接收通知的evAnotherTimeout过程
  -- 空实现用于编译
  procedure evAnotherTimeout (this : in out ConcreteObserver_t) is null;

private

  -- *此处编译失败,与Alarms包中的dummyCallback问题相同*
  evTimeoutCallback : constant Alarms.Callback_t := evTimeout'Access; 

  -- *此处编译失败,与Alarms包中的dummyCallback问题相同*
  evAnotherTimeoutCallback : constant Alarms.Callback_t := evAnotherTimeout'Access; 

  type ConcreteObserver_t is new Alarms.AlarmObserver_t with 
    record
      -- 自定义属性
      Null;
    end record;

end ConcreteObserver;

内容的提问来源于stack exchange,提问作者Albatros23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 05:16:22