博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript使用接口
阅读量:6412 次
发布时间:2019-06-23

本文共 4580 字,大约阅读时间需要 15 分钟。

在经典的Java面向对象语言中,可以用关键字interface来定义接口,用implement来实现接口,而JavaScript虽然也是面向对象语言,但是它并没有内置这些,不过由于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+" 定义的不一致");就会抛出异常。

为什么使用接口

  • 在大型项目中,有利于团队协作(比如分工等)
  • 降低代码的耦合度,从某种意义上讲使代码更加灵活
  • 提高开发效率,通过接口的定义可以先“用上”接口,等接口被实现之后即可得到验证,而不需要进行等待

转载于:https://www.cnblogs.com/hlwyfeng/p/6099957.html

你可能感兴趣的文章
kaptcha可配置项
查看>>
JavaMail邮箱验证用户注册
查看>>
系统时间——ntpd
查看>>
反射实现AOP动态代理模式(Spring AOP实现原理)
查看>>
Spring MVC 4.x + fastjson 1.2.7,封装的List<?>参数
查看>>
js选中问题
查看>>
CentOS 7 Shell脚本编程第二讲 Shell 脚本创建和执行
查看>>
protobuf
查看>>
4.Java基础复习--Set
查看>>
七:Mysql的乐观锁与悲观锁机制
查看>>
CSS滤镜及渐变 (filter样式表属性)
查看>>
调用上面的@InitBinder 解决客户端上传时间参数转换的问题
查看>>
net.sf.json.JSONException: There is a cycle in the hierarchy异常,解决方法
查看>>
OpenStack centos版安装(二)
查看>>
Android自动化测试方向
查看>>
QT中常用数据之间转换
查看>>
向量的内积,长度,正交性
查看>>
app包中的fragment和v4包中的fragment的使用的区别
查看>>
Http协议与缓存
查看>>
监测超过特定内存阀值进程并结束
查看>>