3.4理解继承
一.基于原型的继承:
步骤:
(1)在子类构造函数中调用基类构造函数,从而继承基类的属性。
(2)将基类的一个新实例赋给子类,从而继承基类的方法。
Samples.Cat=function() { Samples.Pet.call(this); } Samples.Cat.prototype =new Samples.Pet(); //测试代码 Samples.Pet.registerClass('Samples.Pet'); Samples.Cat.registerClass('Samples.Cat'); |
调用:
var cc=new Samples.Cat(); cc.set_name("白猫"); cc.speak(); |
覆盖方法:
Samples.Cat.prototype.speak=function (){alert ('meeeewooooo')}; |
二.Microsoft Ajax Library从一个基类派生子类
function Pet() { this._name; this._age; } Pet.prototype={ speak:function (){ alert (this._name+"Meeeeooow"); } } Cat=function (){ Cat.initializeBase(this ); //处理继承并调用基类构造函数 Samples.Cat.registerClass('Samples.Cat',Samples.Pet) |
调用:代码不变
覆盖方法:
Samples.Cat.prototype={ speak:function (){ alert ("Meeeeooow"); } } |
测试:代码不变
3.4.2向基类传递参数
Samples.Pet= function (name ,age) { this._name=name ; this._age=age; } ….. Samples.Cat=function (name,age) { Samples.Cat.initializeBase(this,[name,age]); } ………….. 调用 var cat=new Samples.Cat ("Kitty",1); cat.speak(); |
3.4.3覆写
一.调用基类的方法。callBaseMethod.
子类名.callBaseMethod(this,”方法名”,[参数名表])
Samples.Cat.prototype={ speak:function (){ Samples.Cat.callBaseMethod(this,'speak'); } } |
3.5理解接口和枚举
3.5.1接口
接口:可以使一个对象知道另一个对象能做什么。接口是一个类与外部世界之间定义的一个合约。
一.定义接口
Type.registerNamespace ('Samples'); Samples.IComparable=function (){ //定义一个接口,抛出异常是为防止被当作构造函数。 throw Error .notImplemented (); } Samples.IComparable.prototype={ //定义一个名为compareTo的方法。 CompareTo:function (comparand){ throw Error .notImplemented (); //抛出异常是为防止方法直接被调用。 } } Samples.IComparable.registerInterface('Samples.IComparable'); //注册接口。 |
二.实现接口
Samples.Temperature=function (value){ this._value=value ; } Samples.Temperature.prototype={ CompareTo:function (comparand){ //具体实现 } } Samples.Temperature.registerClass('Samples.Temperature',null ,Samples.IComparable); |
三.综合示例:
<script type ="text/javascript" > Type.registerNamespace ('Samples'); Samples.IComparable=function (){ //定义一个接口,抛出异常是为防止被当作构造函数 throw Error .notImplemented (); } Samples.IComparable.prototype={ //定义一个名为compareTo的方法。 CompareTo:function (comparand){ throw Error .notImplemented (); //抛出异常是为防止方法直接被调用。 } } Samples.IComparable.registerInterface('Samples.IComparable');//注册接 //实现接口 Samples.Temperature=function (value){ this._value=value ; } //类的功能:两个温度(对象类型)进行比较,相等为0,大于为 1,小于为-1; Samples.Temperature.prototype={ CompareTo:function (comparand){ if(Samples.Temperature.isInstanceOfType(comparand)) //检查类型,判断是不是Samples.Temperature对象类型. { var thisValue=this.get_value(); var comparandValue=comparand.get_value(); if(thisValue ==comparandValue ) //相等返回0 return 0; return (thisValue >comparandValue )?1:-1; //不同返回1或-1. } else { throw Error .argumentType ();} //类型不对 }, get_value:function() { alert (this._value); return this._value; } , set_value:function (value){ this._value=value ; } }//end method Samples.Temperature.registerClass('Samples.Temperature',null ,Samples.IComparable); //在方法中调用类 Sys .Application .add_load (Page_Load); function Page_Load() { var tem=new Samples.Temperature(); //没有参数的构造方法来自于接口。 tem .set_value(3); var tem2=new Samples.Temperature(8); var i=tem.CompareTo(tem2); alert (i); // var k= new Samples.IComparable(4); //接口不能定义对象。 } </script> |
3.5.2枚举
枚举:为数字指定名称的一种方法。
一.枚举的定义:
Type.registerNamespace('Samples'); Samples.FileAccess=function (){ //枚举不需要实例化 throw Error .notImplemented(); } Samples.FileAccess.prototype={ //枚举区分大小写。 Read:1,Writer:2,Execute:4 } Samples.FileAccess.registerEnum('Samples.FileAccess',true ); //定义枚举, |
二.枚举的使用
var tempi=Samples.FileAccess.Read; //获取枚举单个值。 alert (tempi ); var rwPermission=Samples.FileAccess.Read|Samples.FileAccess.Writer; alert (rwPermission); //0000 0001 |0000 0010 = 0000 0011 =3 有1则为1 var rPermission=rwPermission&Samples.FileAccess.Writer; alert (rPermission); // 0000 0011 & 0000 0010 = 0000 0010 = 2 相同为1,不同为0 |
3.6使用类型返射
反射:是一种在运行时发现对象有关信息的过程。
3.6.1反射方法
P77表3-1:
3.6.2确定对象类型
alert ("Samples.Temperature是一个类吗?:"+Type .isClass (Samples.Temperature )); //true
alert ("Samples.IComparable是一个接口吗?:"+Type .isInterface(Samples.IComparable ));//true
alert ("是一个命名空间吗?:"+Type .isNamespace (Samples));//true
alert ("Samples.Temperature的名字是什么?:"+Samples.Temperature.getName());//Samples.Temperature
alert ("Samples.Temperature是否实现了接口Samples.IComparable"+Samples.Temperature.implementsInterface(Samples.IComparable));//true
alert ("Samples.Temperature所实现的接口的列表"+Samples.Temperature.getInterfaces()); |
3.6.3构建一个简章的类浏览器
演示:P79 例3-15
3.7处理事件
尽管DOM对象可以产生事件,传统JavaScript对象却不能。Microsoft Ajax Library提供了一个事件模型,使得在客户对象中产生事件。
对事件的处理分两个过程:公开事件与订阅和处理事件。
3.7.1公开事件
公开一个事件的过程如下:
(1)创建一个增加事件处理程序的方法。
(2)创建一个删除事件处理程序的方法。
(3)创建一个负责产生事件的方法。
增加和删除事件的方法必须遵循Microsoft Ajax Library定义的命令约定:
(1)增加事件的方法必须形如:add_事件名
(2)删除事件的方法必须形如:remove_事件名
Sys.EventHanlerList类,用于为多个事件存储多个事件处理程序。
一个类要公开事件,需要在构造函数中创建这个类的实例,并把它存储在一个私有属性中。
this._events=new Sys.EventHandlerList();//事件方法会将与事件处理程序列表交互来管理事件处理程序。
事例:
Type .registerNamespace("Samples"); Samples.Collection=function (){ this._innerList=[]; this._events=null ; } Samples.Collection.prototype={ add:function (member){ this._innerList.push(member ); this._reiseEvent('itemAdded',Sys .EventArgs .Empty ); }, get_events:function (){ if(!this._events){ this._events=new Sys.EventHandlerList(); } return this._events ; } , add_itemAdded:function (handler){ this.get_events().addHandler('itemAdded',handler ); }, remove_itemAdded:function (handler){ this.get_events().removeHandler('itemAdded',handler ); }, _reiseEvent:function (eventName,eventArgs){ var handler=this.get_events().getHandler(eventName ); if(handler ){ if(!eventArgs ){ eventArgs=Sys .EventArgs .Empty ; } handler (this,eventArgs); } } }//end Collection.prototype Samples.Collection.registerClass('Samples.Collection'); |
3.7.2订阅与处理事件
订阅:调用一个负责增加事件处理程序的方法。
Sys .Application .add_load(Page_Load ); function Page_Load() { var collection=new Samples.Collection();//订阅事件 collection .add_itemAdded(OnItemAdded ); collection .add("测试1");collection .add("测试2"); collection .add("测试3"); } function OnItemAdded(sender,e) { alert ("向示例中增加一个新项目"); } |