https://udn.epicgames.com/Three/UnrealScriptDelegates.html
概述
一个代理是到一个绑定到对象上的函数的引用。它们的主要用途是提供函数调用机制,比如,在用户界面系统中提供事件通知。
声明代理
您需要做的第一件事情是声明一个代理。代理声明看上去和事件声明类似。例如:
Class Button extends Window; delegate OnClick( Button B, int MouseX, int MouseY );
将代理作为函数参数
在虚幻引擎 3 中,代理可以用作为函数参数。您首先需要按照上面的方式声明一个代理。然后,您可以在函数中像这样来使用该声明的代理:
function DoStuff(delegate<OnClick> ClickDelegate) { }
当调用这个函数时,与声明的代理具有同样函数声明的函数可以被作为参数传入。例如:
function MyOnClick( Button B, int MouseX, int MouseY ) { } function CallFunction() { DoStuff(MyOnClick); }
调用代理
调用代理的工作方式和调用普通函数一样:
Class Button extends Window; var int MouseDownX, MouseDownY; delegate OnClick( Button B, int MouseX, int MouseY ); function MouseDown( int MouseX, int MouseY ) { MouseDownX = MouseX; MouseDownY = MouseY; } function MouseUp( int MouseX, int MouseY ) { if( MouseX == MouseDownX && MouseY == MouseDownY ) OnClick( Self, MouseX, MouseY ); }
或者使用代理作为函数参数的情况:
function DoStuff(delegate<OnClick> ClickDelegate) { ClickDelegate(Self, MouseX, MouseY); }
分配代理指向一个函数
要想使用代理做一些事情,您需要为它分配一个函数。通常这个函数是在另一个对象中的。要想把一个函数的引用分配给一个代理,函数声明必须和作为代理声明具有精确地一样的参数类型和返回类型(如果有)。这里是一个实例:
Class MyDialogBox extends Window; var Button OKButton, CancelButton; function MyClick( Button B, int MouseX, int MouseY ) { if( B == OKButton ) SaveDetails(); CloseWindow(); } event Initialized() { OKButton = CreateWindow(class‘Button‘, 40, 100, 64, 32 ); CancelButton = CreateWindow(class‘Button‘, 120, 100, 64, 32 ); OKButton.Caption = "OK"; CancelButton.Caption = "Cancel"; OKButton.OnClick = MyClick; CancelButton.OnClick = MyClick; }
在 Create
的最后两行,它把两个按钮的代理都分配为 MyDialogBox 的 MyClick
函数。当 Button 类的 MouseUp
函数调用 OnClick
代理时,作为替换将会调用 MyDialogBox 的 MyClick
函数。如果没有代理,那么您需要创建 Button 类的子类并实现这个功能。
可替换地,您可以在类的 defaultproperties{}
块中分配代理,如下所示:
DefaultProperties { OKButton.OnClick=MyClick CancelButton.OnClick=MyClick }
您也可以把一个代理分配为 None ,这将会导致当调用该代理时,它不会做任何事情。
作为函数参数传入的代理反过来也可以用于在这个类中分配代理属性。
function DoStuff(delegate<OnClick> ClickDelegate) { OKButton.OnClick = ClickDelegate; }
代理和删除的对象
当您删除了一个代理引用的 Actor,然后再调用代理函数时,该代理将什么也不做,就像把它的值分配为 None 一样。
在非 Actor 对象中,代理引用的作用和一般的对象引用一样,并且它会防止那个对象被垃圾回收。如果您在没有删除到一个非 Actor 对象的其中一个函数的代理引用的情况下删除那个对象,那么对该代理的调用将会导致系统崩溃。
为代理声明代理体
您可以为代理声明代理体,比如:
Class Button extends Window; delegate OnClick( Button B, int MouseX, int MouseY ) { Log("This is the default action"); }
如果您在 OnClick
delegate(代理)指向 None 时调用这个代理,那么它将执行代理的函数体。当没有分配 OnClick
的值时,您可以使用这个机制来提供默认的动作。