Asp.net Ajax的客户端框架扩展了Javascript语言。扩展了Javascript的6个原生对象的方法,添加了许多.Net程序员熟悉的方法。如:string.format()。
额们知道Javascript是基于对象的,并没有完全支持面向对象。很多面向对象的特性在Javascript里面是没法实现的:继承,多态,抽象,接口。正是这些软肋导致了许多大型的程序无法用Javascript来进行开发。但是这种时代已经结束了!接下来我们就来一一描述如何用Asp.net Ajax客户端框架开发出面向对象的程序,以及该框架是如何实现面向对象中的那几个重要概念。
在Asp.net Ajax客户端框架中可以这么定义命名空间:
Type.registerNamespace(“MyNamespace”);
这里的类不能单独的定义,必须把类包装进命名空间中。就是在定义类的时候必须先定义命名空间。
Type.registerNamespace(“MyNamespace”); MyNamespace.MyClass=function(cName) { This._name=cName; }; MyNamespace.MyClass.prototype= { DoSomething:function(param) { Alert(“SomeThing!”); } , DoSomething2:function() { Alert(“SomeThing!”); } }//end prototype MyNamespace.MyClass.registerClass(“MyNamespace.MyClass”);
registerClass方法的详细使用情况:
registerClass(类名[字符型])
registerClass(类名[字符型],父类[对象])
registerClass(类名[字符型],接口[对象])
registerClass(类名[字符型],父类[对象],接口[对象])
面向对象编程的核心技术,面向对象的编程精髓就是让程序解耦。针对抽象编程,针对接口编程都是实现程序解耦的重要手段,所以接口在OO世界里是非常的重要滴。
定义接口:
IMyInterface=function(){}; ImyInterface.prototype= { DoSomeThing:function(){}, DoSomeThing2:function(){} } ImyInterface.registerInterface(“IMyInterface”);
实现接口:
MyClass=function(cName) { This._name=cName; }; MyClass.prototype= { DoSomeThing:function() { Alert(‘Dosomething’); } , DoSomeThing2:function() { Alert(‘DoSomeThing2’); } } MyClass.registerClass(“MyClass”,null,ImyInterface);
这里的接口是伪接口,并没有像C#这类真正面向对象语言中的那么强大。它没法实现真正意义上的“针对接口编程”。但是如果我们结合框架中的反射方法还是能基本实现“针对接口编程”。看代码:
Function testClass(cName) { This._name=cName; } Var myclass1=new MyClass(“ghostbear”); Var myclass2=new testClass(“ghostbear”); Var objectQueue=new Array(); objectQueue.push(myclass1); objectQueue.push(myclass2); for(var tmp in objectQueue) { If(ImyInterface.isImplementedBy(objectQueue[tmp]))//确定是否实现了接口 { //调用ImyInterface接口中的DoSomething方法 objectQueue[tmp].DoSomeThing(); //调用ImyInterface接口中的DoSomething方法 objectQueue[tmp].DoSomeThing2(); } Else { Continue; } }
定义枚举:
CapType=function(){}; CapType.prototype= { YellowCap:1, RedCap:2, BlueCap:3, BlackCap:4 }; CapType.registerEnum(“CapType”);
使用枚举:
Alert(CapType.YellowCap);//使用的时候无需实例化,直接使用。
在继承中主要有以下比较重要的概念:1.调用父类的方法;2.覆盖父类的方法;3.抽象方法。
parentClass=function(cName) { this._name=cName; }; parentClass.prototype= { DoSomeThing:function() { alert('DoSomeThing'); } , DoSomeThing2:function() { alert('DoSomeThing2'); } }//end prototype parentClass.registerClass('parentClass'); childClass=function(cName) { childClass.initializeBase(this,[cName]);//调用父类的构造函数 }; childClass.prototype= { DoSomeThing:function() { alert('DoSomeThing By childClass'); } , DoSomeThing3:function() { //调用父类的方法 childClass.callBaseMethod(this,'DoSomeThing'); } }//end prototype childClass.registerClass('childClass',parentClass); var pc=new parentClass('gb'); var cc=new childClass('gb'); cc.DoSomeThing(); cc.DoSomeThing2(); cc.DoSomeThing3();
这里的反射并没有那么强大,框架中的反射更像是用来修补面向对象框架中产生的缺陷。
测试代码:
///////////////////////////////////////////////////////////////////////////////////////////////////// // 用Asp.net Ajax 客户端的反射类方法 // // 作者:GhostBear // // 完成日期:2011年4月28日 // //////////////////////////////////////////////////////////////////////////////////////////////// IWork=function(){}; IWork.prototype= { Do:function(){} }; IWork.registerInterface('IWork'); IFavorite=function(){}; IFavorite.prototype= { LikeDo:function(){} } IFavorite.registerInterface('IFavorite'); people=function(firstName,lastName) { this._firstName=firstName; this._lastName=lastName; }; people.prototype= { get_firstName:function() { return this._firstName; } , get_lastName:function() { return this._lastName; } , ToString:function() { return this._firstName+' '+this._lastName; } , LikeDo:function() { return 'i like do something'; } };//end prototype people.registerClass('people',null,IWork); employee=function(firstName,lastName,salary) { people.initializeBase(this,[firstName,lastName]); this._salary=salary; }; employee.prototype= { get_salary:function() { return this._salary; } , ToString:function() { return this._salary; } , Do:function() { return 'i can do something'; } }//end prototype employee.registerClass('employee',people,IWork); MsgType=function(){}; MsgType.prototype= { Lower:1, Normal:2, Hight:4 } MsgType.registerEnum('MsgType',true); var p=new people('jim','green'); var jim=new employee('jim','green',3000);
方法名称 |
方法简介 |
示例代码 |
getName |
获取类的名字 |
var myType=people; alert(myType.getName()); 结果: People
|
isClass |
判断一个对象是否为类 |
alert(Type.isClass(employee)); 结果: True |
isNamespace |
是否为命名空间 |
Type.registerNamespace('MyNamespace'); alert(Type.isNamespace(MyNamespace)); 结果: true |
getInterfaces |
获取某一对象的所有接口 |
employee.registerClass('employee',people,IWork,IFavorite,Iabc); var iArray=employee.getInterfaces(); for(var tmp in iArray) { alert(iArray[tmp].getName()); } 结果: IWork,IFavorite,Iabc |
isInterface |
是否为接口 |
alert(Type.isInterface(IWork)); 结果 True |
getBaseType |
获取顶层父类constructor |
//alert(employee.getBaseType()) 结果: function(firstName,lastName) { this._firstName=firstName; this._lastName=lastName; }; |
initializeBase |
调用父类的构造函数 |
|
resolveInheritance |
手动解决继承问题,通过拷值的方法。 |
|
callBaseMethod |
调用父类的某个方法 |
|
getBaseMethod |
获取父类的某个方法的定义 |
//alert(employee.getBaseMethod(jim,'ToString')); 结果: function() { return this._firstName+' '+this._lastName; } |
implementsInterface |
查看某对象是否实现某接口 |
alert(employee.implementsInterface(IWork)); 结果: true |
inheritsFrom |
是否继承某个类 |
alert(employee.inheritsFrom(people)) 结果: true |
isImplementedBy |
是否实现某个接口 |
|
getRootNamespaces |
获取所有根命名空间 |
Type.registerNamespace('MyNamespace'); var nArray=Type.getRootNamespaces(); for(var tmp in nArray) { alert(nArray[tmp].getName()); } 结果: Sys,MyNamespace |
Parse |
将序列化的内容类型化 |
var parseType=Type.parse('employee'); var myParseType=new parseType(); alert(parseType.implementsInterface(IWork)); alert(myParseType.Do()); 结果: true,i can do something |
isEnum |
是否为枚举变量 |
alert(Type.isEnum(MsgType)); 结果: true |
isFlag |
确定某个枚举变量的子类型是否支持与操作 |
alert(MsgType.Lower | MsgType.Normal); alert(Type.isFlags(MsgType)); 结果: 3,true |
这样做有什么好处?实现几个设计模式来证明这样做的强大之处。
观察者模式:
/////////////////////////////////////////////////////////////////////////////////////////// // 用Asp.net Ajax 客户端的脚步库实现的观察者模式 // // 作者:GhostBear // // 完成日期:2011年4月24日 // //////////////////////////////////////////////////////////////////////////////////// Type.registerNamespace('Firm');//定义命名空间 Firm Firm.PaperFirm=function(fName) { this._name=fName; this._customers=new Array(); }; Firm.PaperFirm.prototype= { AddCustomer:function(customer) { this._customers.push(customer); } , RemoveCustomer:function(customer) { for(i=0;i<this._customers.length;i++) { //找到了删除对象 if(this._customers[i]._name==customer._name) { this._customers.splice(i,1);//删除对象 } } } , NotifyCustomer:function() { for(i=0;i<this._customers.length;i++) { this._customers[i].ReceiveNotify('快来拿报纸!'); } } }//end prototype Firm.PaperFirm.registerClass('Firm.PaperFirm');//定义类 PaperFirm Firm.ICustomer=function(){}; Firm.ICustomer.prototype= { ReceiveNotify:function(msg){} }; Firm.ICustomer.registerInterface('Firm.ICustomer'); //定义接口 ICustomer Firm.Customer=function(cName) { this._name=cName; } Firm.Customer.prototype= { ReceiveNotify:function(msg) { alert(this._name+' '+msg); } } Firm.Customer.registerClass('Firm.Customer',null,Firm.ICustomer);//定义类Customer,该类实现了接口ICustomer var chinaPaperFirm=new Firm.PaperFirm('中国日报'); var jim = new Firm.Customer('Jim'); var lucy = new Firm.Customer('Lucy'); var bill = new Firm.Customer('Bill'); var book=new chinaPaperFirm.AddCustomer(jim); chinaPaperFirm.AddCustomer(lucy); chinaPaperFirm.AddCustomer(bill); chinaPaperFirm.NotifyCustomer(); chinaPaperFirm.RemoveCustomer(jim); chinaPaperFirm.NotifyCustomer();