从Java的角度理解Ext的extend

发表于:2011-12-29 09:33

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:Adley    来源:51Testing软件测试网采编

  现在我们来分析一下Ext中的继承重头戏Observable,它位于Ext.util这个包下,它的意思即是观察者,使用观察者模式,EDA模式,UI组件就利用这种基于观察和事件的机制进行通信和渲染。

  所有的UI组件都继承这个类,我们看看它的构造函数

  1. EXTUTIL.Observable = function(){    
  2.     var me = this, e = me.events;  
  3.     if(me.listeners){  
  4.         me.on(me.listeners);  
  5.         delete me.listeners;  
  6.     }  
  7.     me.events = e || {};  
  8. };

  这个构造函数不需要参数,在java中,这种父类的构造可以自动的调用默认构造函数,但是这里要注意,if(me.listeners)依赖了子类的构造行为,这在面向对象原则中似乎是一个禁忌,但是如果一个继承体现完全由一个团队维护,他们同时制定继承规则和继承规范,这也无可厚非,这里的listeners可以在子类中不提供,可以让构造出来的对象自己调用on方法来添加监听器,同理这里的events,如果子类没构造会被赋值为一个空对象。那么这个Observable构造器做了两个事,一个是看子类是否在对象上放了监听器,如果放了,就调用对象的on方法进行事件和监听的绑定,二是看子类是否在对象上放置了events,如果没有就把对象的events属性设置为一个空对象。也就是说子类是完全可以不做任何事的,子类只负责自己的数据构造和行为覆盖或追加,events在和监听器绑定之后就是一个Ext.util.Event对象的容器,见这行代码: me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);也就是说,在Ext中,一个活生生的能够响应事件的对象有一个Event容器,它保存了这个对象可以响应什么事件以及事件被触发后被调用的监听器。

  Observable原型上放置的方法都是子类继承的方法,子类的对象就可以在运行时调用这些方法,如下:

  原型上放置了一个静态变量和一些方法,这些方法都是和事件以及监听有关,注意Observable的原型是一个新的对象直接量,它的constructor属性肯定指向的是Object,不是指向的Observable,这岂不是存在bug,我通过代码检测发现alert(Ext.util.Observable.prototype.constructor == Ext.util.Observable);的结果确实又是true,怎么回事呢?答案就在Ext.extend的那段防御性代码,大家回过去看看吧!

  现在我们写一个继承Obervable的类,不过不是UI组件,而是一个领域模型,比如论坛帖子,它在被修改之后会跑出一个被修改的事件,监听器捕获这个事件将修改保存到数据库中,代码如下:

  1. ForumThread = Ext.extend(Ext.util.Observable, {  
  2.                 constructor: function(config) {  
  3.                     this.name = config.name;  
  4.                     //把监听器放进超类的属性  
  5.                     this.listeners = config.listeners;  
  6.  
  7.                     this.events = {"change" : true};  
  8.  
  9.                     //给领域模型设置事件,通过上面的写法也可以  
  10.  /*                   this.addEvents({  
  11.                                 "change" : true  
  12.                             });*/ 
  13.  
  14.                     //调用超类构造超类不变量  
  15.                     ForumThread.superclass.constructor.call(this, config)  
  16.                 },  
  17.                 //领域行为,会触发事件  
  18.                 changeName : function(newName) {  
  19.                     alert("原主题名字是:" + this.name);  
  20.                     this.name = newName;  
  21.                     alert("更改后主题名字是:" + this.name);  
  22.                     this.fireEvent("change"this);//触发事件  
  23.                 }  
  24.             });  
  25.  
  26.     Ext.onReady(function() {  
  27.         var forumThread = new ForumThread({  
  28.                     name : '关于将Jdon框架提升为DCI框架的设想',  
  29.                     //构造领域模型时注入监听处理程序  
  30.                     listeners : {  
  31.                         change : function(thread) {  
  32.                             alert('接受到事件,将异步保存新的名字:' + thread.name);  
  33.                         }  
  34.                     }  
  35.                 });  
  36.         //领域行为调用  
  37.         forumThread.changeName("关于将Jdon框架提升为DCI框架的设想,整合JdonMVC");  
  38.     });

  如果事件设置和监听绑定直接在子类完成,那么就不必显式调超类构造函数

  1. ForumThread = Ext.extend(Ext.util.Observable, {  
  2.             constructor: function(config) {  
  3.                 this.name = config.name;  
  4.                 this.events = {"change" : true};  
  5.                 this.on(config.listeners);  
  6.             },  
  7.             //领域行为,会触发事件  
  8.             changeName : function(newName) {  
  9.                 alert("原主题名字是:" + this.name);  
  10.                 this.name = newName;  
  11.                 alert("更改后主题名字是:" + this.name);  
  12.                 this.fireEvent("change"this);//触发事件  
  13.             }  
  14.         });

55/5<12345
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号