Delegates
出自OpenFace
第二十二章 委派
第四部分 进阶概念
本章描述委派(Delegates)的使用,它是OpenLaszlo应用程序用于当属性值改变时彼此间通信机制的一部分。
我们通常只需要知道在脚本语言中为对象创建委派(Delegates)。对于你用标签创建的对象,例如<view>你可以使用事件处理管理通信。当使用处理时,OpenLaszlo在运行时为你管理委派(Delegates)。Delegates仍然存在与幕后,但系统透明的管理它们。尽管如此,理解标签和基于脚本的事件语法是很有帮助的。
本文的最后部分解释了委派(Delegates)在其他的程序语言中中的相似性。
目录 |
概况
委派的目的是在程序运行时为特定的方法绑定一个事件。这样"用委派记录一个事件" ,简单的理解就是给这个方法临时绑定了该事件。事件约束在方法的范围内,这意味着,事件发生时方法被执行了,直到这个委派被注销。
值得注意的是,即使在编译时你不了解委派(Delegates)。你依然可以使用它,在程序运行时触发委派的事件,产生的名字会作为一个参数值传递。
在LZX中,委派(Delegates)和事件相互参照定义。委派(Delegates)是指定调用方法的对象,并且事件是存储委派的对象。
事件发生时,它轮流调用所有的委派(Delegates)。委派(Delegates)可以被看作是实例的已命名的方法。
尽管委派(Delegates)可以与标签产生的对象一起使用,但明确的创建的委派(Delegates)通常用于在脚本中创建的对象。
委派(Delegates)是必要的,因为有些时候你不知道编译时具体的事件应该做什么。例如,假定有一个视图,你想创建一个方法在每次按键时调用。这时,要用标签。当有时想要的事件行为依赖于事件创建的时间。那时你就要用委派(Delegates)。
LzDelegate
使用LzDelegate类创建和管理委派(Delegates):
创建委派(Delegates)的语法如下:
LzDelegate(object, method, sender, event)
第3,4个参数是可选的:
var del = new LzDelegate(object, method, sender, event);
与之同样的是:
var del = new LzDelegate(object, method); del.register(sender, event);
委派(Delegates)和标签事件的关系
Lzdelegate类用于在脚本中创建委派。 您可以通过如下方法静态的附加一个事件处理:
<handler name="eventName" reference="eventSender">
...what to do...
</handler>
但若在编译时不知道事件名或事件传送媒介,就需要使用动态方法实现:
<method name="methodName">
...what to do...
</method>
<method name="createDelegate>
this.myDel = new LzDelegate(this, "methodName", eventSender, "eventName");
</method>
事件处理自动的为您处理产生和记录代表的所有工作:
oninit="do something or other";
expands to:
<handler name="oninit" >
do something or other;
</name>
Which expands to:
// make up a unique method name
var uid = $m + <unique id>
// make a method of that name to run the onclick code
this.$m = function () { ; };
// make a delegate for that method
var del = new LzDelegate(this, $m);
// register it to receive onkeydown events
del.register(this, 'onkeydown');
下例在使用中说明类LzDelegate。
Example 22.1 运行时记录事件
<canvas height="100">
<view id="v1" x="0">
<text id="statusText" bgcolor="green" resize="true" text="start over"/>
<method name="regbutton" >
if( (typeof this.del) == "undefined" ) {
this.del = new LzDelegate(this, "buttonclickedagain" );
}
this.del.register(this, "onx" );
</method>
<method name="startover">
this.del.unregisterAll();
this.reset();
</method>
<method name="reset">
this.setAttribute("x", 50);
statusText.setAttribute("text", "Nothing special");
</method>
<method name="buttonclickedagain">
this.setAttribute("x", 100);
statusText.setText("That button was clicked two or more times");
</method>
</view>
<handler name="oninit">
v1.startover();
v1.regbutton();
v1.setAttribute("x",10);
</handler>
</canvas>
代理和存储管理
当销毁一个对象时,例如,释放存储view的内存。尽管如此,销毁view并没有销毁与它相关的委派(Delegates)。应该手动注销委派(Delegates)一释放它占用的存储空间。
存储管理的例子
使用委派(Delegates),动态的为事件添加一个方法:
Example 22.2 代理和存储
<class ...>
<method name="doit"> ... </method>
<method name="init">
super.init();
this.myDel = new LzDelegate(this, 'doit', libraryName, 'onload');
</method>
<method name="destroy">
this.myDel.unregisterAll(); // "destroys" delegates
super.destroy();
</method>
</class>
委派(Delegates)作为属性的用法
委派(Delegates)是对象,它同样可以最为另一个对象的属性。例如:
Example 22.3 代理作为属性的用法
<class name="createdelegate">
<attribute name="mydel" type="expression" value="$once{new LzDelegate(this, 'handler')}"
</class>
上面的代码在实例类时创建了委派(Delegates)模型。这种声明委派(Delegates)的技术具有易读的优点,并且可以确保只创建了一个委派(Delegates)。
关于其它语言中的委派(Delegates)
这是对您可能熟悉的编程语言的委派(Delegates)的简要的讨论。
委派(Delegates)是方法指针。它是一种方式:当我调用它时就会调用对象o的方法m。(与函数指针相反,它并不捕获对象)在Java中,可以使用匿名内部类得到同样的效果。(java使用函数创建实例)在Lisp中,使用关闭(Lisp使用context创建函数)。【Java和Lisp只是相反的两个方面】。
基本的:
// constructor
LzDelegate = function(o, m) { this.o = o; this.m = m; }
LzDelegate.prototype.execute = function () { with (this) { return o[m](); } };
var del = new LzDelegate(object, 'method');
del.execute();
与..相同:
// constructor
function makeDelegate (o, m) { return function () { return o[m](); }; };
var del = makeDelegate(object, 'method');
del();
这里可以看到使用函数(方法)触发捕获context的‘o’,‘m’的实例和触发捕获context的‘o’and‘m’的函数作为关闭使用是类似的。

