Typecast Generic type to other type

只愿长相守 提交于 2019-12-12 00:52:14

问题


i have a base class

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

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

And a derived generic class

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


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

when base class Notify is call it give me error "Incompatible types: 'WideString' and 'T'" and when i do **Notify(WideString(aMap))** it says invalid typecast

my question is how can i type cast generic type to "WideString" so that i can call base class notify


回答1:


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

Here you have aMap which is a generic argument, of type T. The type T has no constraints on it. It can be any type. You are seeking to convert aMap to WideString. The compiler simply has no way to do that. There is no over-arching conversion that can take an argument of arbitrary type and convert it to WideString.

You could push aMap into a TValue, and then call the ToString method of TValue. The compiler will at least be satisfied with this:

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

This might do what you expect. Or perhaps not. It all depends upon what T happens to be. If T is a fundamental type like Integer or string then TValue.ToString will almost certainly do what you expect. If T is more esoteric then who knows whether this code will behave as you expect. You certainly have not given us any indication as to how the arbitrary type is to be converted to text.


The thing that I suspect you are not grasping about generics is that the compiler has to know how to compile the method without knowing what the generic type is. In comments you state that:

aMap is not of type class

Whilst you might know that, the compiler does not. From the perspective of the compiler, T can be anything at all. Generics are very different from Smalltalk/C++ templates where the compilation happens after instantiation.

The generics functionality does allow you to apply constraints to your generic type. However, these are quite limited. You cannot apply a constraint that says, type T will have a well-defined implicit conversion to WideString.

As I have said to you before, I sense that you are struggling with your understanding of generics. I feel that it would be more productive for you to present the underlying problem rather than you proposed solution.


One final point. The WideString type is a wrapper around the COM BSTR string type. In modern Unicode aware Delphi you use WideString just when writing interop code with COM. You should be using string rather than WideString. The string type is an alias for UnicodeString, the native Delphi Unicode string type.




回答2:


You are looking for something like this?

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;


来源:https://stackoverflow.com/questions/26650581/typecast-generic-type-to-other-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!