Typecast通用类型到其他类型

时间:2014-10-30 10:29:24

标签: delphi generics delphi-xe2 delphi-xe5 delphi-xe4

我有一个基类

 TEventMulticaster = class(Tobject)
 public
   procedure Notify(aMap: WideString);
 end;

 procedure TEventMulticaster.Notify(aMap: WideString);
 begin
  // Do something 
 end;

派生的通用类

  TEventMulticaster<T> = class(TEventMulticaster)
   public
     procedure Notify(aMap: T ); reintroduce;
   end;


  procedure TEventMulticaster<T>.Notify(aMap: T);
  begin
    inherited Notify(aMap)  // ERROR
  end;

当基类Notify被调用时,它会给我错误“不兼容的类型:'WideString'和'T'” 当我**Notify(WideString(aMap))**时,它表示无效的类型转换

我的问题是如何将强制转换泛型类型键入“ WideString ”,以便我可以调用基类notify

2 个答案:

答案 0 :(得分:4)

procedure TEventMulticaster<T>.Notify(aMap: T);
begin
  inherited Notify(aMap);
end;

这里有aMap,它是T类型的通用参数。类型T没有约束。它可以是任何类型。您正在寻求将aMap转换为WideString。编译器根本无法做到这一点。没有过度转换可以采用任意类型的参数并将其转换为WideString

您可以将aMap推送到TValue,然后调用ToString TValue方法。编译器至少会对此感到满意:

inherited Notify(TValue.From<T>(aMap).ToString);

这可能会达到您的预期。或许不是。这完全取决于T恰好是什么。如果T是基本类型,例如Integerstring,则TValue.ToString几乎肯定会按预期执行。如果T更深奥,那么谁知道此代码是否会按预期运行。你当然没有给我们任何关于如何将任意类型转换为文本的指示。


我怀疑你没有理解泛型是因为编译器必须知道如何在不知道泛型类型的情况下编译方法。在评论中,您声明:

  

aMap不是类型

虽然您可能知道,但编译器却不知道。从编译器的角度来看,T可以是任何东西。泛型与Smalltalk / C ++模板非常不同,后者在实例化后进行编译。

泛型功能允许您将约束应用于泛型类型。但是,这些都非常有限。您不能应用一个约束,该约束说明,类型T将具有明确定义的隐式转换为WideString

正如我之前告诉过你的,我觉得你正在努力理解你对仿制药的理解。我觉得提供基础问题而不是您提出的解决方案会更有效率。


最后一点。 WideString类型是COM BSTR字符串类型的包装。在现代的Unicode识别Delphi中,只需在使用COM编写互操作代码时使用WideString。您应该使用string而不是WideStringstring类型是UnicodeString的别名,是本机Delphi Unicode字符串类型。

答案 1 :(得分:1)

您正在寻找类似的东西吗?

TEventMulticaster = class
end;

TEventMulticaster<T> = class( TEventMulticaster )
public
  procedure Notify( AMsg : T );
end;

TEventMaster = class
private
  FEvents : TList<TEventMulticaster>;
public
  procedure Notify<T>( AMsg : T );
end;

procedure TEventMaster.Notify<T>( AMsg : T );
var
  LEvent : TEventMulticaster;
begin
  for LEvent in FEvents do
    if LEvent is TEventMulticaster<T> then
      ( LEvent as TEventMulticaster<T> ).Notify( AMsg );
end;