问题
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