注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

itoedr的it学苑

记录从IT文盲学到专家的历程

 
 
 

日志

 
 

JavaScript之接口使用(转)  

2016-11-25 11:24:14|  分类: html5-webapp |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
为什么使用接口呢?其原因大多就这几条:1) 在大型项目中,有利于团队协作(比如分工等) 2)降低代码的耦合度,从某种意义上讲使代码更加灵活 3)提高开发效率,通过接口的定义可以先“用上”接口,等接口被实现之后即可得到验证,而不需要进行等待

javascript中接口的意义:         

在经典的Java面向对象语言中,可以用关键字interface来定义接口,用implement来实现接口,而JavaScript虽然也是面向对象语言,但是它并没有内置这些,不过由于JavaScript的灵活性,我们可以通过模拟来实现,方法是使用一个辅助类和辅助函数来协助完成这一过程。javascript中的接口就类似于java中的interface,是用function定义的语句块。在javascript中模仿接口 -----首先,我们可以定义一个公共的接口类: Interface,接着我们考虑下接口类需要有哪些成员和方法。 1)接口是一组方法签名的集合,其他内置接口的语言可以在接口中进行函数声明,从而定义一个接口;而在javascript中,我们需要通过给Interface类增加一个数组成员,保存方法名称,我命名为:methods,另外还有个成员:name,这个成员是接口名,方便我们快速定位错误—比如我们的对象到底是没实现哪个接口的哪个方法;2) 在有内置接口的语言中,若一个类继承了某个接口,而未实现其中的一个或多个方法时,编译器会报错,从而提醒开发人员,但是javascript是无法提供这个功能的,所以在我们的Interface类中需要一个方法来保证在未实现某接口的所有方法时,抛出一个错误。 这个方法我们可以命名为:ensureImplents, 另外这个方法是可通用的,所以可以作为一个静态方法,即Interface的方法,而不需要在其每个实例中保存。

其实,javascript中,接口实质就是一个函数.


参考代码

先把例子写出来,后面再讲解一些细节:

// 辅助类var Interface = function(name,methods){

if(arguments.length != 2){

throw new Error("参数数量不对,期望传入两个参数,但是只传入了"+arguments.length+"个参数");

}

this.name = name;

this.methods = [];

for(var i = 0, len = methods.length; i < len; i++){

if(typeof methods[i] !== "string"){

throw new Error("期望传入的方法名是以字符串的格式类型,而不是"+ (typeof methods[i]) + "类型");

}

this.methods.push(methods[i]);

}}// 辅助函数Interface.ensureImplements = function(object){

if(arguments.length < 2){

throw new Error("期望传入至少两个参数,这里仅传入"+arguments.length+"个参数");

}

for(var i = 1; i < arguments.length; i++){

var interface = arguments[i];

if(!(interface instanceof Interface)){

throw new Error(arguments[i] + "不是一个接口");

}

for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++){

var method = interface.methods[j];

if(!object[method] || typeof object[method] !== "function"){

throw new Error("对象的方法 "+method+" 与接口 "+interface.name+" 定义的不一致");

}

}

}}//接口var RobotMouth = new Interface('RobotMouth',['eat','speakChinese','speakEnglish']);var RobotEar = new Interface('RobotEar',['listen']);// 实现RobotMouth、RobotEar接口// 构造函数var Robot = function(){}; Robot.prototype = {

// 实现RobotMouth接口

eat: function(){

console.log("I can eat");

},

speakChinese: function(){

console.log("I can speak Chinese");

},

speakEnglish: function(){

console.log("I can speak English");

},

// 实现RobotEar接口

listen: function(){

console.log("I can listening");

}};var miniRobot = new Robot();function useRobot(robot){

Interface.ensureImplements(miniRobot,RobotMouth,RobotEar);

robot.eat();

robot.listen();}useRobot(miniRobot);

运行结果:

I can eat

I can listening

下面对这段代码进行讲解:

定义接口

//接口var RobotMouth = new Interface('RobotMouth',['eat','speakChinese','speakEnglish']);var RobotEar = new Interface('RobotEar',['listen']);

我们定义了两个接口,通过new Interface()来定义接口,在Interface这个函数中:

  • 第一个参数是接口名称

  • 第二个参数是一个数组,数组是元素是字符串的格式,里面分别是接口定义的方法

上述的代码,可理解为做下面的这样的定义:

/*interface RobotMouth(){ function eat(); function speakChinese(); function speakEnglish();}interface RobotEar(){ function listen();}*/

现在我们来看一下Interface() 这个构造函数:

// 辅助类var Interface = function(name,methods){

if(arguments.length != 2){

throw new Error("参数数量不对,期望传入两个参数,但是只传入了"+arguments.length+"个参数");

}

this.name = name;

this.methods = [];

for(var i = 0, len = methods.length; i < len; i++){

if(typeof methods[i] !== "string"){

throw new Error("期望传入的方法名是以字符串的格式类型,而不是"+ (typeof methods[i]) + "类型");

}

this.methods.push(methods[i]);

}}

这个构造函数实现的是对传入的参数进行严格的校验,如果参数不对就会报错。这里首先是判断参数的个数,第二是判断传入的方法名是否是字符串的格式。

接口的实现

接口定义好后,通过一个类来实现,这里要注意的是,需要给出明确的注释,说明这个类实现的是哪个接口。

// 实现RobotMouth、RobotEar接口// 构造函数var Robot = function(){}; Robot.prototype = {

// 实现RobotMouth接口

eat: function(){

console.log("I can eat");

},

speakChinese: function(){

console.log("I can speak Chinese");

},

speakEnglish: function(){

console.log("I can speak English");

},

// 实现RobotEar接口

listen: function(){

console.log("I can listening");

}};

这里我们定义了一个Robot构造函数来实现以上两个接口,方法写在原型上,注意注释明确。

使用接口

var miniRobot = new Robot();function useRobot(robot){

Interface.ensureImplements(miniRobot,RobotMouth,RobotEar);

robot.eat();

robot.listen();}useRobot(miniRobot);

首先我们创建了一个实例叫miniRobot,然后做为参数传入useRobot() 这个函数进行生产调用,在这个函数里的第一行代码Interface.ensureImplements(miniRobot,RobotMouth,RobotEar); 是对传入的miniRobot进行严格的校验,校验不通过会抛出异常。它接受的参数必须大于等于两个:

  • 第一个参数是一个实现了接口的对象

  • 第二个参数是对象的一个接口

  • 第三个参数同上(若存在的话)

我们来看一下这段代码:

// 辅助函数Interface.ensureImplements = function(object){

if(arguments.length < 2){

throw new Error("期望传入至少两个参数,这里仅传入"+arguments.length+"个参数");

}

for(var i = 1; i < arguments.length; i++){

var interface = arguments[i];

if(!(interface instanceof Interface)){

throw new Error(arguments[i] + "不是一个接口");

}

for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++){

var method = interface.methods[j];

if(!object[method] || typeof object[method] !== "function"){

throw new Error("对象的方法 "+method+" 与接口 "+interface.name+" 定义的不一致");

}

}

}}

首先对传入的参数进行校验,必须传入两个或以上的参数。

然后检查每个传入的接口是否已经定义,如果未定义,就抛出异常,表示不是一个接口。

然后对每个接口定义的方法进行遍历,与第一个参数(实现接口的对象)进行比较,如果对象没有实现接口的方法,那么这段代码throw new Error("对象的方法 "+method+" 与接口 "+interface.name+" 定义的不一致");就会抛出异常。

  评论这张
 
阅读(30)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017