Delphi 中的变量泛型?

erhoui1w  于 2023-06-22  发布在  其他
关注(0)|答案(1)|浏览(104)

Context

我尝试在 Delphi 中创建一个通用的“Observer”模式,我成功地实现了一些功能:

TObserver = class
  protected
    FSubject: TSubject;
  public
    constructor Create(); virtual; overload;
    constructor Create( constref subject: TSubject ); virtual; overload;
    destructor Destroy(); virtual;
    procedure ReAttach( constref newSubject: TSubject ); virtual;
    procedure Update(constref subject: TSubject); virtual;
  end;

  TSubject = class
  protected
    FObservers: TList<TObserver>;
  public
    constructor Create; overload;
    destructor Destroy; override;
    procedure Notify(); virtual;
    procedure Attach(constref AObserver: TObserver); virtual;
    procedure Detach(constref AObserver: TObserver); virtual;
  end;

每个新的回调签名都需要扩展TSubject和TObserver。这很快就变得乏味。

TMyObserver = class( TObserver )
public
  type TCallback = procedure (...) of object;
private
  FCallback: TCallback;
public
  property Callback: TCallback read FCallback write FCallback;
  procedure Update(constref subject: TSubject, ...); overload;
end;

TMySubject = class( TSubject )
...

这是不切实际的,所以我想知道是否有更好的方法。
例如,在C++中,有一个叫做Variadic Templates的东西,在 Delphi 中可能会被称为Variadic Generics

#include <iostream>
#include <functional>

template <typename ...UpdateArgs>
class Observer
{
public:
    using CallbackType = std::function<void(UpdateArgs...)>;
    
    CallbackType callback;
    
    void Update(UpdateArgs... args)
    {
        if (callback) callback(args...);
    }
};

int main()
{
    Observer<int, const std::string&> obs1;
    obs1.callback = [](int vInt, const std::string& vStr)
    {
        std::cout << "Int is: " << vInt << " and String is: '" << vStr << "'" << std::endl;
    };
    obs1.Update(42, "Hi you");
    
    // OR
    
    Observer<float> obs2;
    obs2.callback = [](float f)
    {
        std::cout << "Float is: " << f << std::endl;
    };
    obs2.Update(3.1415926);

    return 0;
}

Test it live here
对于那些不太熟悉C++的人来说,这基本上是一个带有可变数量参数的泛型Observer。使回调可用于所需参数的确切类型和数量。

提问

Delphi 有Variadic泛型吗?也就是说,一种指定可变参数集的方法,允许为每个所需的通知签名专门指定TObserverTSubject
我希望解决方案是类型安全的。
否则,还有什么选择?

w8rqjzmb

w8rqjzmb1#

Delphi 有Variadic泛型吗?
不,不是的。泛型所能做的一切都在Embarcadero的DocWiki中得到了完整的记录:
https://docwiki.embarcadero.com/RADStudio/en/Generics_Index

相关问题