我有一个基类
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
答案 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
是基本类型,例如Integer
或string
,则TValue.ToString
几乎肯定会按预期执行。如果T
更深奥,那么谁知道此代码是否会按预期运行。你当然没有给我们任何关于如何将任意类型转换为文本的指示。
我怀疑你没有理解泛型是因为编译器必须知道如何在不知道泛型类型的情况下编译方法。在评论中,您声明:
aMap不是类型
虽然您可能知道,但编译器却不知道。从编译器的角度来看,T
可以是任何东西。泛型与Smalltalk / C ++模板非常不同,后者在实例化后进行编译。
泛型功能允许您将约束应用于泛型类型。但是,这些都非常有限。您不能应用一个约束,该约束说明,类型T将具有明确定义的隐式转换为WideString
。
正如我之前告诉过你的,我觉得你正在努力理解你对仿制药的理解。我觉得提供基础问题而不是您提出的解决方案会更有效率。
最后一点。 WideString
类型是COM BSTR
字符串类型的包装。在现代的Unicode识别Delphi中,只需在使用COM编写互操作代码时使用WideString
。您应该使用string
而不是WideString
。 string
类型是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;