Determine when a TRttiMethod is marked as overload, override or abstract
-
29-09-2019 - |
Question
Is possible using the Rtti determine if a TRttiMethod
is a marked as overload
,override
or abstract
?
thanks in advance.
Solution
Overload: I don't think there's an RTTI flag for this, but you can check to see if there's more than one method with the same name. That's not perfect, but it's probably as close as you're going to get.
Override: First, make sure the method is virtual. (Or dynamic or message dispatch.) Then check the class's ancestors for other methods with the same name and VirtualIndex property.
Abstract: Deep in the implementation section of rtti.pas, in with a bunch of method data flags, is one called mfAbstract
, defined as 1 shl 7;
. There's no code that references this, but it is implemented in the RTTI generated by the compiler. When you have a TRttiMethod reference for the method, you can test it like this:
IsVirtual := PVmtMethodExEntry(method.Handle).Flags and (1 shl 7) <> 0;
PVmtMethodExEntry is declared in the TypInfo
unit, so you'll need to use it for that to work.
OTHER TIPS
If it still matters... I check it this way:
1. function GetCloneProc: TRttiMethod;
2. var
3. methods: TArray<TRttiMethod>;
4. parameters: TArray<TRttiParameter>;
5. begin
6. methods := BaseType.GetDeclaredMethods;
7. for Result in methods do
8. begin
9. if (Result.MethodKind = mkProcedure) and (Result.Name = 'CloneTo') and
10. (Result.DispatchKind = dkStatic) and not Result.IsClassMethod then
11. begin
12. parameters := Result.GetParameters;
13. if (Length(parameters) = 1) and (parameters[0].Flags = [pfAddress]) and
14. (parameters[0].ParamType.TypeKind = tkClass) and
15. ((parameters[0].ParamType as TRttiInstanceType).MetaclassType = (BaseType as TRttiInstanceType).MetaclassType) then
16. Exit;
17. end;
18. end;
19. Result := nil;
20. end;
You should pay attention to line #10. Virtual or Dynamic methods have DispatchKind dkVtable
and dkDynamic
respectively. So if method marked as abstract
it must have one of them. In the same time to avoid getting class static
method as the result I use second condition: not TRttiMethod.IsClassMethod
See also System.Rtti:
TDispatchKind = (dkStatic, dkVtable, dkDynamic, dkMessage, dkInterface);
You can handle this enumeration at one's discretion.
About "override": see TStream.Seek
, maybe you'll find something useful for you there.
About "overload": the answer of @mason-wheeler above looks pretty good for this case.