Procedure di ordine superiore in delphi

Aug 22 2020

Sto tentando di fare riferimento a una procedura come parametro di un'altra procedura e ho difficoltà a comprendere la documentazione.(http://docwiki.embarcadero.com/RADStudio/Sydney/en/Procedural_Types_(Delphi))

Da quello che ho capito ho bisogno di creare un nuovo tipo per la procedura..

type
  TCallback = procedure of object;

e dichiarare la procedura di ordine superiore comeprocedure HigherOrder(pProc: TCallback);

Ricevo l'errore di compilazione " E2010 Tipi incompatibili: 'TCallBack' e 'procedura, puntatore non tipizzato o parametro non tipizzato' " quando provo a chiamare la funzione (quando si fa clic sul pulsante)

type
  TCallBack = procedure of object;
  TfrmMain = class(TForm)
    btnAct: TButton;
    procedure btnActClick(Sender: TObject);
  private
    procedure HigherOrder(pProc: TCallback);
    procedure Callback();
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

{ TfrmMain }

procedure TfrmMain.btnActClick(Sender: TObject);
begin
  HigherOrder(Callback()); <--Error occurs here
end;

procedure TfrmMain.Callback;
begin
  //Do some stuff
end;

procedure TfrmMain.HigherOrder(pProc: TCallback);
begin
  //Do some other stuff
  pProc();
end;

end.

Qualsiasi aiuto è molto apprezzato. Sono abbastanza nuovo nella programmazione in Delphi.

Risposte

11 RemyLebeau Aug 22 2020 at 14:32

Il problema è che stai chiamando Callback() prima e poi provando a passare il suo valore di ritorno (che, non ne ha uno) a HigherOrder(), ma non è quello che ti HigherOrder()aspetti, motivo per cui ricevi l'errore. In altre parole, il tuo codice è approssimativamente equivalente a questo:

procedure TfrmMain.btnActClick(Sender: TObject);
begin
  //HigherOrder(Callback());
  var res := Callback();
  HigherOrder(res);
end;

Solo che il tipo di non resè definito poiché Callback()è a proceduree non a function.

Quando si chiama HigherOrder(), è necessario rimuovere la ()parentesi finale da Callback()per passare Callback se stesso (beh, il suo indirizzo di memoria, comunque) come valore del pProcparametro, ad esempio:

procedure TfrmMain.btnActClick(Sender: TObject);
begin
  HigherOrder(Callback);
end;

Sì, puoi anche eliminare la parentesi quando chiami una procedura senza passarle alcun parametro. Ma, in questo caso, il compilatore è abbastanza intelligente da sapere che l' Callbackidentificatore che omette le parentesi viene assegnato a un tipo di chiusura e quindi lo passerà così com'è e non lo chiamerà .