面向对象在JavaScript中的接口实现

接口是面向对象编程的基础。它是一组包括了函数型方法的数据结构,与类一样。都是编程语言中比較抽象的概念。比方生活中的接口。机顶盒。人们利用它来实现收看不同频道和信号的节目,它宛如对不同类型的信息进行集合和封装的设备。最后把各种不同类型的信息转换为电视可以识别的信息。在编程语言中的接口,实际上是不同类的封装并提供统一的外部联系通道,这样其它对象就行利用接口来调用不同类的成员了。

——整理自《jQuery开发从入门到精通》

接口的概念

构造函数(类)是详细的实现,接口是类的约定。

API接口(应用程序接口)、人机交互接口、电源接口、USB接口等尽管用途不同,功能各异。可是都包括一个共同的特性:约定、规范。

能够说,接口就是一张契约和合同,它约定了设计者和使用者都必须遵循的要求。

接口承诺了详细类应该事先的功能。

举一个非常有必要的样例,在java中实现接口,比方以下的代码:

interface Base{
  void function1();
  void function2();
  void function3();
}

Base接口承诺了3个基本功能:function1()、function2()、function3()。

这个接口就像是一份合同。在甲方(调用类的用户)和乙方(定义类的开发者)之间约定。

乙方负责实现接口约定的功能。功能的实现就是所谓的类。例如以下实例:

class App implements Base   // 定义一个App类,用这个类来实现接口Base

类App将遵照接口的约定。

专业来说就是。应用类App继承Base接口类。

它的详细实现例如以下:

class App implements Base{
  void function1(){
    System.out.println("I am fun1");
  }
  void function2(){
    System.out.println("I am fun2");
  }
  void function3(){
    System.out.println("I am fun3");
  }
}

这样。乙方实现了这个接口,而甲方也应该来依照接口的约定去使用类App即可了。

所以说。接口(interface)和类(class)。实际上都是同样的数据结构。

在接口中能够声明属性,方法,事件。类型,但不能声明变量,且不能设置被声明成员的详细值(功能实现)。

也就是说,接口仅仅能定义成员。不能给定义的成员赋值。而接口作为它的继承类或派生类的约定,继承类或派生类共同完毕接口属性、方法、事件、类型的实现。在接口和实现类之间,无论是方法名还是属性调用顺序上都应保持一致。

接口的目的就是约束编码。促使代码规范。对于强类型语言是必须的。也是非常重要的环节。

可是对于JavaScript弱类型语言来说,严格的类型检查会束缚JavaScript的灵活性。非常多前端开发者根本不用接口,但不会影响脚本的设计。

使用接口的优点:减少对象间的耦合度,提高代码的灵活性。学会使用接口,可以让手中的函数变得机灵,这在大型开发中是非常重要的。

对于JavaScript来说,本身不支持接口功能,没有提供内置方法。可是人工设计一个额外的接口程序,又会对程序的性能产生影响。

项目越大。这样的开销越大。

所以,用不用接口能够遵循两个条件:

① 项目大小,假设是一个框架,使用接口在一定程度上会提高程序的性能。

假设是简单的应用,就不必使用接口了。

② 假设对JavaScript接口比較熟练,多用接口也能够。假设操心过多使用接口影响性能,则能够在考虑产品公布前,清除接口功能模块。或者设置接口的运行条件。

防止它被频繁运行。影响性能。

接口的实现

JavaScript中并不支持接口。可是我们能够模仿其它语言,来定义接口。

以下来规划接口结构的设计和检測功能的实现:

(1) 设计一个接口辅助的类结构,这个构造函数相当于一个过滤器。用于在接口实例化过程中,检測初始化參数是否合法。假设符合接口设计标准,则把第2个參数中每一个方法名和參数个数以数组元素的形式输入接口内部属性methods。

在输入前分别检測每一个參数类型是否符合规定。

同一时候检查參数是否存在残缺,并即时以0补齐參数。

function Interface(name,methods){ // 接口辅助类,參数包含接口实例的名称和方法集
  if(arguments.length!=2){ // 假设參数个数不等于2,抛出异常。

throw new Error(‘标准接口约定。须要两个參数‘);
  }
  this.name = name; // 存储第一个參数值,实例化后就是接口实例的名称
  this.methods = []; // 接口实例的方法存储器
  if(methods.length < 1){ // 假设第二个參数的元素个数为0,说明是空数组。抛出异常。
    throw new Error(‘接口的第二个參数不能为空‘);
  }
  for(var i = 0; i < methods.length; i++){ // 開始对第2个參数的元素进行遍历检測
    var item = methods[i];
    if(typeof item[0] !== ‘string‘) { // 假设第二个參数的第一个元素不是string类型,抛出异常
      throw new Error("接口约定的第一个參数应为字符串");
    }
    if(item[1]&&typeof item[1] !== ‘number‘){ // 假设第二个參数有第二个元素,且第二个元素不是number类型,抛出异常
      throw new Error(‘接口约定的第个參数应为数值‘);
    }
    if(item.length == 1){ // 假设第二个參数仅仅有一个元素。那么手动给它加入第二个元素 0
      item[1] = 0;
    }
    this.methods.push(item); // 把符合规定的方法存储到数组存储器中。

}
}

(2) 为接口辅助类 Interface 定义一个方法 implements,该方法将检測实现类是否符合接口实例的约定。

它至少包含两个參数,第1个參数o表示实现类。第2个參数及其后面的參数表示该类将要实现的接口标准。也就是说,能够为一个类指定多个接口约定,这样就能够更灵活的分类设计接口实例。然后遍历第二个及其后面的全部參数,在循环结构中,先洁厕接口是否为接口标准的实例,否则就会抛出异常。

再从接口实例的方法存储器中逐一读取方法名,填入类中来验证类的方法是否符合接口实例设置的标准,验证包含方法名、function类型和參数个数。假设有问题,马上抛出异常。

Interface.implements = function(o){  // 用于检測类方法是否符合接口实例的约定 。此处的o,将来会是类中的this
  if(arguments.length<2){ // 检測该方法传递的数值是否符合规定
    throw new Error("接口约定类应包括至少两个參数。");
  }
  for(var i=1;i<arguments.length; i++){ // 遍历检測类所遵循的实例是否合法
    var interface = arguments[i]; // 这里interface表示接口的实例对象。

if(interface.constructor !== Interface){
      throw new Error(‘从第2个以上的參数必须为接口实例‘);
    }
    for(var j=0;j<interface.methods.length;j++){ // 检測类方法是否符合接口实例的约定
      var method = interface.methods[j][0];
      if(!o[method] || typeof o[method] !== ‘function‘ || o[method].length!==interface.methods[j][1]) {
        throw new Error("该实现类没能履行" + interface.name + "接口方法" + method + "约定");
      }
    }
  }
}

(3) 实例化接口标准,Interface 接口不过个构造函数,也就是个框架协议,还没有制定类应该遵循的详细标准。框架协议中。已经设计好了监測逻辑,一旦实例化接口。并指明类应遵守的约定,那么应用该标准的实例的类就必须准守。

以下依据Interface接口标准定义了6个详细的接口实例。

// 设置接口的不同实现实例
var Get = new Interface("Get",[["get",0]]);
var Set = new Interface("Set",[["set",1]]);
var Saying = new Interface("Saying",[["saying",1]]);
var Base = new Interface("Base",[["get",0],["set",1]]);
var Base1 = new Interface("Base1",[["set",1],["get",0]]);
var Base2 = new Interface("Base2",[["get",0],["set",1],["saying",1]]);

(4) 在类中定义应该实现的标准,即类应该遵循的接口约定。

// 创建一个木驴类
function Neddy(){
  this.name = ‘‘;
  Interface.implements(this,Base,Get,Set); // 让木驴类实现接口的实例,能够指定多个。也能够仅仅有一个。
}
// 依照接口实例来定义 两个方法get,set
Neddy.prototype.get = function(){
  return this.name;
}
Neddy.prototype.set = function(name){
  this.name = name;
}

(5) 在类中设置了多个接口实例。我们来进行检測

// 检測接口实现
var neddy = new Neddy();
neddy.set("Testing");
console.log(neddy.get()); // Testing

成功完毕接口的应用,这里,假设在Neddy类中,我们让它实现的接口实例和 Neddy.prototype中给类定义的方法不统一,或者接口与接口之间有冲突,就会抛出异常。比方我们能够改动Neddy中的接口实现。再给它加入一个接口实例Base2,就会报异常。由于我们没有依照接口的协议,给Neddy加入saying()方法。

上面的举例仅仅是用js来模拟实现接口功能,在实际开发中,我们须要依据不同的需求,开发不同的接口。

扩展知识 :

检測函数的參数列表一般有三种形式

① arguments.callee.length

② 函数名.length

③ arguments.length

当中 ① 和 ② 是一样的,③ 视详细情况而定。

一般函数声明式的定义有个默认属性name继承自Object ,举比例如以下:

  function fn(x,y){
    console.log(fn.name); // fn
    console.log(arguments.callee.name); // fn
    console.log(fn.length); // 2
    console.log(arguments.callee.length); // 2
    console.log(arguments.length); // 视详细情况而定
  }
  fn(1,2,3); // 分别输出 fn fn 2 2 3

为了说明上面接口检測參数长度 o[method].length  的问题 ,举比例如以下:

function A(){}
A.prototype.say = function (x,y,z,o) {}
var a = new A();
console.log(a[‘say‘].length); // 4
时间: 2024-10-07 07:52:07

面向对象在JavaScript中的接口实现的相关文章

前端开发:面向对象与javascript中的面向对象实现(一)

前端开发:面向对象与javascript中的面向对象实现(一) 前言: 人生在世,这找不到对象是万万不行的.咱们生活中,找不到对象要挨骂,代码里也一样.朋友问我说:“嘿,在干嘛呢......”,我:“找不到对象!”,他:“就你那样也能找得到对象?”.我一脸黑线...... 废话不多说,今天博主要跟大家聊的是<面向对象与javascript中的面向对象实现>”. 面向对象理解: 面向对象是一种对现实世界理解和抽象的方法,是一种先进的程序设计理念,是一种比较抽象的,多形态的设计模式.我们可以这么理

前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型

前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的影响,单单是自己的念想受到了一定得局限,想法不能够像平地而起的高楼大厦建成一样.可是那大楼也是有烂尾的呀,我觉得最重要的还是外在环境与个人观念的先决条件,决定了拖延症的症状的好坏,有那么一些人,它也有拖延症,但是它在拖的中间,想的更多,看的更远.事情在做的时候更加有条不紊,这拖延症这样看来,它也是好

JavaScript设计模式之----接口的实现

1.接口 (1)什么是接口? 接口是提供了一种用以说明一个对象应该具有哪些方法的手段.尽管它可以表明这些方法的语义,但它并不规定这些方法应该如何实现.例如,如果一个接口包含有一个名为setName的方法,那么你有理由认为这个方法的实现应该具有一个字符串参数,并且会把这个参数赋给一个name变量.有了这个工具,你就能按对象提供的特性对它们进行分组.例如,即使一批对象彼此存在着极大的差异,只要它们都实现了Comparable接口,那么在object.compare(anotherObject)方法中

JavaScript设计模式: 接口模仿

JavaScript中模仿接口有三种方法 1. 注释法 /* interface Composite(){ function add(child); function remove(child); function getChild(index); } interface FormItem(){ function save(); } */ 缺点:无法确保真正实现接口中的方法集,也不会抛出错误以告知用户程序中有问题,对测试和调试没有什么帮助.它主要属于程序文档范畴,在这种做法中,对接口约定的遵守完

深入JavaScript(一)——JavaScript中的面向对象(一)

面向对象的语言有一个标志,那就是它们都有"类"的概念,通过类可以创建任意多个具有相同属性和方法的对象.JavaScript 中没有类的概念,因此它的面向对象与基于类的语言中的对象有所不同. JavaScript 对对象的定义是:无序属性的集合,其属性可以包含基本值.对象或者函数.可以把 JavaScript 对象理解成散列表,即一组名值对,其中的值可以是数据或函数. 那么想要创建自定义对象,有以下几种常用方法: 1.使用 Object 构造函数: var person = new Ob

javaScript中的面向对象表示

我们知道,面向对象的语言都有一个特点,那就是一般都有类的概念,进而有类的属性和方法等概念. 然而javaScript中并没有类的概念,那我们怎么去通过这个语言本身去实现一些面向对象的特性呢? (1)一个最简单的方式 创建Object的实例,为它添加属性和方法 var car = new Object(); //创建实例 car.color = "red"; //为car这个对象增加颜色的属性 car.showColor= function(){ //car的方法 alert(this.

如何理解并学习javascript中的面向对象(OOP) [转]

如果你想让你的javascript代码变得更加优美,性能更加卓越.或者,你想像jQuery的作者一样,写出属于自己优秀的类库(哪怕是基于 jquery的插件).那么,你请务必要学习javascript面向对象,否则你无法更灵活的使用javascript这门语言. 什么事闭包?到底什么是原型?(知道闭包和原型的,就算得上是javascript的高手了.但真正能够理解,并且灵活运用的人并不多)到底该如何学习javascript中的面向对象呢?在javascript这么语言正如日中天,相信不少人正在为

javascript 中的面向对象实现 如何封装

面向对象的手法来封装javascript ,javascript是没有类的概念的. 所以今天谈到的封装,其实就是用javascript的函数来实现的. 1 2 3 4 var People{ name:’一介布衣’, age:’30' }; 这就是javascript中的一个对象,里面封装了2个属性. 实例化一个对象的实例 people 1 2 var people=new People(); console.log(people.name,people.age);  //一介布衣,30 如果我

深入理解javascript中实现面向对象编程方法

介绍Javascript中面向对象编程思想之前,需要对以下几个概念有了解: 1. 浅拷贝和深拷贝:程序在运行过程中使用的变量有在栈上的变量和在堆上的变量,在对象或者变量的赋值操作过程中,大多数情况先是复制栈上的信息,这样就会出现以下情况,如果变量是对象,那么这一操作,复制的只是真正对象所在 的堆内存空间的起始地址,这就是所谓的浅拷贝,如果是深拷贝,则是在内存堆空间中重新分配一个内存,并把分配的内存的起始地址复制过去. 2. 引用类型数据和值类型数据:谈到引用类型数据和值类型数据,自然而然的联想到