如果我嘗試使用一個封閉的事件處理程序的編譯器抱怨:我可以使用一個封閉的事件處理程序(即TButton的的OnClick)
不兼容的類型:「方法指針和正常程序」
我明白..但有沒有辦法在方法指針上使用clouser?以及如何定義是否可以?
如:
Button1.Onclick = procedure(sender : tobject) begin ... end;
謝謝!
如果我嘗試使用一個封閉的事件處理程序的編譯器抱怨:我可以使用一個封閉的事件處理程序(即TButton的的OnClick)
不兼容的類型:「方法指針和正常程序」
我明白..但有沒有辦法在方法指針上使用clouser?以及如何定義是否可以?
如:
Button1.Onclick = procedure(sender : tobject) begin ... end;
謝謝!
@Button1.OnClick := pPointer(Cardinal(pPointer(procedure (sender: tObject)
begin
((sender as TButton).Owner as TForm).Caption := 'Freedom to anonymous methods!'
end)^) + $0C)^;
德爾福2010年works
一個很好的問題。
據我所知,目前版本的Delphi中無法做到這一點。這非常不幸,因爲這些匿名過程對於快速設置對象的事件處理程序非常有用,例如在xUnit自動測試框架中設置測試夾具時。
應該有兩種方式CodeGear的實現此功能:
1:允許創建的匿名方法。就像這樣:
Button1.OnClick := procedure(sender : tobject) of object begin
...
end;
這裏的問題是作爲匿名方法的自指針。可以使用創建匿名方法的對象的自指針,但只能從對象上下文創建匿名方法。一個更好的主意可能是在幕後創建一個虛擬對象來包含匿名方法。
2或者,可以允許事件類型接受這兩種方法和過程,只要它們共享定義的簽名即可。這樣,你就可以創建事件處理程序你想要的方式:
Button1.OnClick := procedure(sender : tobject) begin
...
end;
在我的眼裏,這是最好的解決方案。
在以前的Delphi版本中,你可以通過添加隱藏自我指針參數使用常規的程序,事件處理程序和硬盤類型轉換它:
procedure MyFakeMethod(_self: pointer; _Sender: TObject);
begin
// do not access _self here! It is not valid
...
end;
...
var
Meth: TMethod;
begin
Meth.Data := nil;
Meth.Code := @MyFakeMethod;
Button1.OnClick := TNotifyEvent(Meth);
end;
我不知道上面的真編譯,但它應該給你的一般想法。我之前已經完成了這個工作,並且它爲常規程序工作。由於我不知道編譯器爲閉包生成了什麼代碼,我不能說這是否適用於它們。
它易於擴展以下處理更多形式的事件類型。
使用
procedure TForm36.Button2Click(Sender: TObject);
var
Win: TForm;
begin
Win:= TForm.Create(Self);
Win.OnClick:= TEventComponent.NotifyEvent(Win, procedure begin ShowMessage('Hello'); Win.Free; end);
Win.Show;
end;
代碼
unit AnonEvents;
interface
uses
SysUtils, Classes;
type
TEventComponent = class(TComponent)
protected
FAnon: TProc;
procedure Notify(Sender: TObject);
class function MakeComponent(const AOwner: TComponent; const AProc: TProc): TEventComponent;
public
class function NotifyEvent(const AOwner: TComponent; const AProc: TProc): TNotifyEvent;
end;
implementation
{ TEventComponent }
class function TEventComponent.MakeComponent(const AOwner: TComponent;
const AProc: TProc): TEventComponent;
begin
Result:= TEventComponent.Create(AOwner);
Result.FAnon:= AProc;
end;
procedure TEventComponent.Notify(Sender: TObject);
begin
FAnon();
end;
class function TEventComponent.NotifyEvent(const AOwner: TComponent;
const AProc: TProc): TNotifyEvent;
begin
Result:= MakeComponent(AOwner, AProc).Notify;
end;
end.
的方法不具有相同的調用簽名具有相同參數的過程。方法總是將Self作爲「隱藏」參數傳遞。 – 2008-12-25 17:48:42
是的,當然。但我看不出爲什麼編譯器不應該能夠在「幕後」處理這兩種情況。例如,如果需要一個方法,它可以在匿名過程周圍創建一個虛擬類包裝。 – 2009-02-03 08:29:46
這種模式在JavaScript Python等動態語言中非常常見。 – 2013-10-22 08:41:27