01.Javascript中的接口----Interface [转载]
转载地址:http://blog.csdn.net/ymmc001/archive/2010/11/05/5990021.aspx
本文主要讲述如何用原生的Javascript代码来模拟并实现接口
前言
众所周知,在Java、C#等语言中,接口由专门的关键字interface来定义,而接口的实现则有implements关键字来完成,接口有什么特点呢?简单地说有(不完全归纳):
- 不可被实例化
- 所有方法都是抽象方法
- 所有属性都是public static final的
但是在Javascript语言中,没有现成的关键字可以直接用来定义一个接口,也没有现成的关键字可以直接用来实现所谓的extends和implements。既然没有现成的,下面将阐述如何用原生的Javascript代码来模拟并实现接口。
Javascript中的接口
接口的定义
/**
* Interface构造器
* @param {String} name 接口名
* @param {Array} methods 接口中的抽象方法
* @exception {Error} 参数不合格时抛出异常
* @example
* var IActionListener = new Interface("IActionListener",["method1","method2"]);
*/
var Interface = function(name, methods) {
if(arguments.length != 2) {
throw new Error("Interface有且只有两个参数,而当前参数个数为:" + 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("Interface中的方法名必须合法");
}
this.methods.push(methods[i]);
}
};
这个Interface类是用来模仿Java中的interface关键字的,但不同的是,Java中通过interface IActionListener{}的形式来定义一个接口,而这里则是通过var IActionListener = new Interface("IActionListener",["method1"])的形式来定义。
这个接口类接受两个参数,第一个表示需要定义的接口名称,第二个参数表示该接口中即将声明的抽象方法。该类在产生新接口的时候,会检查参数的合法性,只要通过检查,接口便产生了,同时具有两个属性:接口名和方法列表。
接口的实现
/**
* 接口实现的检查,保证object是InterfaceN的实例
* @param {Object} oInterface 待检查的接口实例
* @param {Class} InterfaceN 被实现的Interface
* @exception {Error} 参数不合格时抛出异常
* @example
* Interface.ensureImplements(oActionListener,IActionListener);
*/
Interface.ensureImplements = function(oInterface,Interface1,Interface2,InterfaceN) {
if(arguments.length < 2) {
throw new Error("Interface.ensureImplements方法至少需要两个参数,而当前参数个数为:" + arguments.length);
}
for(var i = 1, len = arguments.length; i < len; i++) {
var interface = arguments[i];
if(interface.constructor !== Interface) {
throw new Error(interface + "不是Interface的实例,不是接口");
}
for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++) {
var method = interface.methods[j];
if(!oInterface[method] || typeof oInterface[method] !== 'function') {
throw new Error("所给参数没有实现" + interface.name + "接口," + method + "未找到");
}
}
}
};
这个静态方法是用来模仿Java中的implements关键字的,但不同的是,Java中通过class ActionListener implements IActionListener{}来实现的,而这里则是通过interface.ensureImplements(oActionListener,IActionListener)的形式来保证的。
这个静态方法接受两个参数,第一个表示接口实现类的实例对象,第二个参数表示接口实现类(当然了,这里其实是一个对象)。方法的内部会校验实例对象是否都实现了接口中的所有抽象方法,如果在该实例中存在没有被实现的抽象方法(方法未找到),则表明该实例对象不是接口实现类的实例对象。
接口实例的创建与使用
//创建接口
var IActionListener = new Interface("IActionListener",["method1","method2"]);
//接口实例的创建
var oActionListener = {
method1 : function(){
alert("这是方法1");
},
method2 : function(){
alert("这是方法2");
}
};
//implements确认
Interface.ensureImplements(oActionListener,IActionListener);
//调用实例中的方法
oActionListener.method1();
这是一个简单的接口定义并实现的过程。
在Javascript中,必然存在着很多种接口的模拟方式,这里只是其中的一种实现思路。
模拟之不当,还请见谅。
非常希望您能提出宝贵的意见。
从ensureImplements方法到implements方法的升级(2010-09-22更新)
前面定义的ensureImplements(oInterface,Interface1,Interface2,InterfaceN)是通过实例来保证的,但是按照常理来说,一个接口被实现以后,便可以进行实例化,但是这里不是真正意义上的实现,而是一种检查、一种保证。为了让接口实现后仍然能通过new关键字实例化对象,下面需要将原来的方法进行升级,于是我定义了下面的方法:implements(ImplementsClass,Interface1,Interface2,InterfaceN),代码如下:
/**
* 接口的实现
* @param {function} ImplementsClass 待实现的类
* @param {object} InterfaceN 被实现的Interface,Interface的实例
* @exception {Error} 参数不合格时抛出异常
* @example
* implements(ActionListener,IActionListener);
*/
var implements = function(ImplementsClass,Interface1,Interface2,InterfaceN){
if(arguments.length < 2) {
throw new Error("Interface.ensureImplements方法至少需要两个参数,而当前参数个数为:" + arguments.length);
}
//保证ImplementsClass的类型为function
if(typeof arguments[0] !== "function"){
throw new Error("实现类的类型必须为function");
}
for(var i = 1, len = arguments.length; i < len; i++) {
var interface = arguments[i];
if(interface.constructor !== Interface) {
throw new Error(interface + "不是Interface的实例,不是接口");
}
//这里循环进行接口抽象方法的实现
for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++) {
var method = interface.methods[j];
if(!arguments[0].prototype[method]){
arguments[0].prototype[method] = function(){};
}
}
}
}
经过这样的升级,我们的代码就可以写成这样了:
//创建接口
var IActionListener = new Interface("IActionListener",["method1","method2"]);
//创建实现类
var ActionListener = function(){};
//实现
implements(ActionListener,IActionListener);
//这个时候,ActionListener.prototype已经是如下这个样子了:
/*
ActionListener.prototype = {
method1 : function(){},
method2 : function(){}
};
*/
//接下来可以真正的填充被空实现的方法的逻辑了
ActionListener.prototype = {
method1 : function(){
alert("这是方法1");
},
method2 : function(){
alert("这是方法2");
}
};
//调用实例中的方法
oActionListener.method1();
OK,一切正常。到此为止,在后续的文章中提到的implements方法,就是这个方法了,请务必留意,谢谢。
浙公网安备 33010602011771号