Search code examples
delphipolymorphismfunction-pointersdelphi-xe7

How to cast between compatible method pointers?


I have two different method pointers.

type
  TComponentMethod = procedure(const AComponent: TComponent) of object;
  TFormMethod = procedure(const AForm: TForm) of object;

The only difference is the type of the argument, but both are object references so it should not make any difference from the calling convention point of view.

(However it could be a type safety problem, because of co- / contravariance.)

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    procedure M2(const AForm: TForm);
  end;

procedure TForm1.FormCreate(Sender: TObject);
var
  FormMethod: TFormMethod;
  ComponentMethod: TComponentMethod;
begin
  FormMethod := M2;
  // How to cast this?
  ComponentMethod := M2;
end;

The compiler doesn't let me do it.

[dcc32 Error] Unit1.pas(32): E2010 Incompatible types: 'TComponent' and 'TForm'

Is there any way to type cast a method pointer to another "compatible" method pointer?


Solution

  • You can do this:

    var
      FormMethod: TFormMethod;
      ComponentMethod: TComponentMethod;
    begin
      FormMethod := M2;
      ComponentMethod := TComponentMethod(FormMethod);
    end;
    

    As far as I can see, the trick is that you need to assign to a temporary local variable before subsequently assigning that to ComponentMethod.

    As you know, this is not typesafe. If ComponentMethod is invoked with an argument that is not derived from TForm, then the compiler won't be able to save you.