我正在考虑一种跟踪对象任何成员变化的通用机制。这个想法基本上是在调用lastModified
时将时间戳保存到某个成员set
。
到目前为止,我的想法是拥有一些父类(这里是伪代码)
class Tracker {
time lastModified;
void onChildSet() {
lastModified = NOW();
}
}
并从我的特定对象继承
public class Object extends Tracker {
sometype member;
void setMember(sometype value) {
member = value;
onChildSet();
}
}
我不喜欢这种方法,我不知道如何避免父类的onChildSet()
显式调用的必要性。实际上我正在寻找一些方法让lastModified
自动更新,而无需编写任何代码。是否有一些概念如何实现?
答案 0 :(得分:1)
使用InvocationHandler。您也可以使用字节码检测自行完成相同的操作,但InvocationHandler更简单
答案 1 :(得分:1)
大多数动态语言都有某种拦截方法调用的方法。例如,所有ruby对象都有一个方法“method_missing”,只要在未定义的对象上调用方法,就会调用该方法。您可以使用此功能设置代理对象以跟踪lastModified值。另一种动态语言,Actionscript 3.0在API中有一个Proxy类。同样,您可以使用此代理类来拦截函数调用。不幸的是,使用这样的代理意味着您必须修改定义方法的方式。在ruby情况下,显然只在方法不存在时调用method_missing。这意味着您必须在对象上定义您的方法,然后由代理类包装。看看我在AS3中放在一起的例子。为了跟踪它的正确性,必须通过trackSet方法定义,我们不能直接在MyObject类上定义方法。 trackSet存储对象中属性的名称以及回调函数。当在代理类上调用setProperty时,将针对setter对象检查属性的名称,如果存在,则为该属性更新lastModified,并调用该属性回调。
package {
import flash.utils.Proxy;
import flash.utils.flash_proxy;
public dynamic class Tracker extends Proxy {
private var setters : Object;
public function Tracker() {
setters = { };
}
public function getLastModified(name : String) : Number {
return setters[name] ? setters[name].lastModified : 0;
}
protected function trackSet(name : String, fn : Function) : void {
setters[name] = {
lastModified: 0,
setter: fn
};
}
override flash_proxy function setProperty(name : *, value : *) : void {
if(!setters[name]) return;
setters[name].lastModified = new Date().time;
setters[name].setter(value);
}
}
}
-
package {
public dynamic class MyObject extends Tracker {
public function MyObject() {
trackSet('member', setMember);
}
private function setMember(val : String) : void {
trace('set member =', val);
}
}
}
-
var obj : MyObject = new MyObject();
obj.member = 'monkey';
trace('member getlast modified at', obj.getLastModified('member'));