RTTI and method overrides

RTTI and method overrides

Is it possible to see that a specific method in the (current) class has an override, using RTTI?

Update: See my comment 12:02 – it was solvable without using RTTI or VMT trickery

21 thoughts on “RTTI and method overrides


  1. I was thinking of having “import/export” methods that could be used for manually copying values to/from a reference – but if those were not overridden for the class – I would try to match properties by name/type.


    If no Export method override existed, I could assume the reference as read only.


  2. It’s only dire if it is not reliable. When you are potentially facing edit forms in the number of hundreds – you really start to appreciate anything that will reduce the amount of boilerplate code.


  3. To clarify – I only want to detect that there is an override in the current class class instance for a method defined in it’s base class.


    Turned out that this was a LOT simpler than I thought – and I didn’t need to fool around with neither VMT nor RTTI.


    unit DetectOverride;


    interface


    type


      TRootClass = class


      private


        FHasImport: boolean;


        FReference: T;


        function GetReference: T;


        procedure SetReference(const Value: T);


      protected


        procedure ImportByRTTI; virtual;


        property HasImport: boolean read FHasImport write FHasImport;


        property HasExport: boolean read FHasImport write FHasImport;


      public


        constructor Create; virtual;


        procedure ImportReference; virtual;


        procedure ExportReference; virtual;


        property Reference:T read GetReference write SetReference;


      end;


      TDerivedClass = class(TRootClass)


      public


        procedure ImportReference; override;


      end;


    implementation


    { TRootClass }


    // This is where the discovery happens


    constructor TRootClass.Create;


    var


      vm: procedure of object;


    begin


      Inherited;


      vm := Self.ImportReference;


      HasImport := TMethod(vm).Code @TRootClass.ImportReference;


      vm := Self.ExportReference;


      HasExport := TMethod(vm).Code @TRootClass.ExportReference;


    end;


    procedure TRootClass.ExportReference;


    begin


      // Manually copy fields internal properties to reference


    end;


    function TRootClass.GetReference: T;


    begin


      if HasExport


       then ExportReference;


      Result := FReference;


    end;


    procedure TRootClass.ImportByRTTI;


    begin


      // Do RTTI magic


    end;


    procedure TRootClass.ImportReference;


    begin


      // Manually copy fields from Reference to internal properties


    end;


    procedure TRootClass.SetReference(const Value: T);


    begin


      FReference := Value;


      if HasImport


       then ImportReference


        else ImportByRTTI;


    end;


    { TDerivedClass }


    procedure TDerivedClass.ImportReference;


    begin


      // In this class, HasImport will be True after create


    end;


    end.


  4. What I have done (simplified), with RTTI is:


    if (FRttiMethod.DispatchKind = dkVtable) then


    begin


      LKind := ‘; virtual’;


      if (FRttiMethod.Parent.BaseType.GetMethod(FRttiMethod.Name).DispatchKind = dkVtable) then


      begin


        LDispatchKind := ‘; override’;


      end;


    end;


    It could be over simplifying things and getting false positives but it seems to be working… 


  5. David Heffernan What is a terrible idea? My way of spotting an method override – or the concept of using RTTI to match properties? For the latter, about as terrible as LiveBindings, I guess.


  6. You don’t mean that. You don’t mean that when you ask a question you only ever want a direct answer to it, and you do not want anyone to expand on the issues around the question. You absolutely do want that. You want us to say, “well, the answer to your question is X, but you’ve probably asked the wrong question, because of Y.”


  7. In this case, I really do mean that. “Because of Y” is not really relevant to the original question. How to do it is relevant. Why I want to do it, really is irrelevant – and it will be up to me to evaluate the risk/reward in the context of where I would be using answer X.