Procedure di ordine superiore in delphi
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
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 procedure
e 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 pProc
parametro, 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' Callback
identificatore che omette le parentesi viene assegnato a un tipo di chiusura e quindi lo passerà così com'è e non lo chiamerà .