2

我正在考虑一种通用机制来跟踪对象的任何成员的变化。这个想法基本上是在调用 a 时将时间戳保存到某个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无需编写任何代码即可自动更新的方法。是否有一些概念如何实现这一目标?

4

2 回答 2

1

使用调用处理程序。您也可以使用字节码检测自己做同样的事情,但 InvocationHandler 更简单

于 2012-08-08T21:05:22.633 回答
1

大多数动态语言都有一些拦截方法调用的方法。例如,所有 ruby​​ 对象都有一个方法“method_missing”,只要对未定义的对象调用方法,就会调用该方法。您可以使用此功能设置代理对象以跟踪 lastModified 值。另一种动态语言,Actionscript 3.0 有一个代理API 中的类。同样,您可以使用此代理类来拦截函数调用。不幸的是,使用这样的代理意味着您必须修改定义方法的方式。在 ruby​​ 的情况下,method_missing 显然只在方法不存在时才被调用。这意味着您必须在一个对象上定义您的方法,然后由代理类包装。看看我在 AS3 中整理的示例。要跟踪的属性必须通过 trackSet 方法定义,我们不能直接在 MyObject 类上定义该方法。trackSet 将属性的名称存储在对象中以及回调函数中。当在代理类上调用 setProperty 时,会根据 setters 对象检查属性的名称,如果存在 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'));
于 2012-08-09T17:35:22.723 回答