跟踪对象的修改

时间:2012-08-08 20:56:50

标签: oop

我正在考虑一种跟踪对象任何成员变化的通用机制。这个想法基本上是在调用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自动更新,而无需编写任何代码。是否有一些概念如何实现?

2 个答案:

答案 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'));