- 解释接口:
在JavaScript的世界中,没有内置的创建或实现接口的方法,也没有可以判断一个对象是否实现了与另一个对象相同的一套方法,这使得对象之间很难互换使用,好在JavaScript拥有出色的灵活性,这使得模拟传统面向对象的接口,添加这些特性并非难事。
在有内置接口的语言中,若一个类继承了某个接口,而未实现其中的一个或多个方法时,编译器会报错,从而提醒开发人员,但是javascript是无法提供这个功能的,所以在我们的Interface类中需要一个方法来保证在未实现某接口的所有方法时,抛出一个错误。 这个方法我们可以命名为:ensureImplents, 另外这个方法是可通用的,所以可以作为一个静态方法,即Interface的方法,而不需要在其每个实例中保存。
接口的利弊:
利:既定的接口具有自我描述性,并能够促进代码的重用性,接口可以提供一种信息,告诉外部一个类需要实现哪些方法。还有助于稳定不同类之间的通信方式,减少了继承两个对象的过程中出现的问题。这对于调试也是有帮助的,在JavaScript这种弱类型语言中,类型不匹配很难追踪,使用接口时,如果出现了问题,会有更明确的错误提示信息。
弊:1.如果大量使用接口会一定程度上弱化其作为弱类型语言的灵活性。
2.JavaScript并没有对接口的内置的支持,只是对传统的面向对象的接口进行模拟,这会使本身较为灵活的JavaScript变得更 加难以驾驭。
3.任何实现接口的方式都会对性能造成影响,某种程度上归咎于额外的方法调用开销。接口使用的最大的问题在于, JavaScript不像是其他的强类型语言,如果不遵守接口的约定,就会编译失败。
js中三种定义接口的方式:
1 注解描述的方式
//1 注解描述的方式
<script type=text/javascript charset=utf-8>
//javascript定义接口的三种方式
//1 注解描述的方式
//优点:程序员可以有一个参考
//缺点:还是属于文档的范畴 ,这种方式太松散了 没有检查接口的方法是否完全被实现
/*
* interface Composite{
* function add(obj);
* function remove(obj);
* function update(obj);
* }
*
*
*/
//CompositeImp1 implements Composite
var CompositeImp1=function(){
}
CompositeImp1.prototype.add=function(obj){
//do something,,,
}
CompositeImp1.prototype.remove=function(obj){
//do something,,,
}
CompositeImp1.prototype.update=function(obj){
//do something,,,
}
var c1=new CompositeImp1();
var c2=new CompositeImp1();
alert(c1.add==c2.add);
</script>2 属性检测的方式
<script type=text/javascript charset=utf-8>
//第二种实现接口的方式 属性检测的方式
/*
* interface Composite{
* function add(obj);
* function remove(obj);
* function update(obj);
* }
* interface FormItem{
* function select(obj);
* }
*
*/
//CompositeImp1 implements Composite,FormItem
var CompositeImp1=function(){
//显示的在类的内部 接受所实现的接口
//一般来说是一个规范 我们项目经理:在类的内部定义一个数组(名字要固定)
//this可以声明变量
this.implementsInterfaces=['Composite','FormItem'];
}
CompositeImp1.prototype.add=function(obj){
//do something,,,
alert('add,,,');
}
CompositeImp1.prototype.remove=function(obj){
//do something,,,
alert('remove,,,');
}
CompositeImp1.prototype.update=function(obj){
//do something,,,
alert('update,,,');
}
CompositeImp1.prototype.select=function(obj){
//do something,,,
alert('select,,,');
}
//检测CompositeItem类的对象的
//类的实现要有个实例 实例需要检测 instance
function CheckCompositeImp1(instance){
//判断当前对象是否实现了所以接口
if(!IsImplements(instance,'Composite','FormItem')){
throw new Error('Object does not implement a required interface');
}
}
//公用的具体的检测方法(核心方法)返回值类型Boolean
//这个方法的主要目的:就是判断 实例对象 有没有实现相关的接口
function IsImplements(object){
//arguments 对象 获得函数的实际参数
for(var i=1;i<arguments.length;i++){
//接受所实现的每一个接口的名字
var interfaceName=arguments[i];
//判断次方法到底成功还是失败
var interfaceFound=false;
//object实例对象有implementsInterfaces属性
for(var j=0;j<object.implementsInterfaces.length;j++){
if(object.implementsInterfaces[j]==interfaceName){
interfaceFound=true;
break;
}
}
if(!interfaceFound){
return false;
}
}
return true;
}
var c1=new CompositeImp1();
CheckCompositeImp1(c1);
c1.add();
</script>
3 鸭式辨型法
<script type=text/javascript charset=utf-8>
//实现接口的第三种方式:鸭式辨型法实现接口(最完美的javascript实现接口方式)
//注解描述法 ,属性检测法测方法)
//鸭式辨型法实现的核心:一个类实现接口的主要目的:把接口里的方法都实现(检
//完全面向对象 代码也实现统一 也解耦了
//一 :接口类 Class Interface===>实例化N多个接口
/*
* 接口类需要2个参数
* 参数1:接口的名字(string)
* 参数2:接受方法名称的集合(数组)(array)
*/
var Interface = function(name, methods){
// 判断接口的参数个数
if (arguments.length != 2) {
throw new Error('this instance interface constructor axguments must be 2 length!');
}
this.name = name;
this.methods = [];//定义一个内置的空数组对象等待接受methods里的元素(方法名字)
for (var i = 0, len = methods.length; i < len; i++) {
if (typeof methods[i] !== 'string') {
throw new Error('the Interface method name is error! ');
}
this.methods.push(methods[i]);
}
}
// 二:准备工作:
//实例化接口对象
var CompositeInterface=new Interface('CompositeInterface',['add','remove']);
var FormItemInterface=new Interface('FormItemInterface',['update','select']);
//CompositeImp1 implements CompositeInterface,FormItemInterface
//2 具体的实现类
var CompositeImp1=function(){
}
//实现接口的方法 implements methods
CompositeImp1.prototype.add=function(obj){
//do something,,,
alert('add,,,');
}
CompositeImp1.prototype.remove=function(obj){
//do something,,,
alert('remove,,,');
}
CompositeImp1.prototype.update=function(obj){
//do something,,,
alert('update,,,');
}
// CompositeImp1.prototype.select=function(obj){
// //do something,,,
// alert('select,,,');
// }
//三 :检验接口里的方法
//如果检验通过 不做任何操作 不通过:浏览器抛出error
//这个方法的目的 就是通过检测方法的
Interface.ensureImplements=function(object){
//如果检测方法接受的参数小于2个 参数传递失败!
if(arguments.length<2){
throw new Error('Interface.ensureImplements method constructo arguments must be>=2');
}
//获得接口实例对象
for(var i=1,len=arguments.length;i<len;i++){
var instanceInterface=arguments[i];
//判断参数是否是接口的类型
if(instanceInterface.constructor!=Interface){
throw new Error('the arguments constructor not be Interface Class');
}
//循环接口实例对象里面的每一个方法
for(var j=0;j<instanceInterface.methods.length;j++){
//用临时变量 接受每一个方法的名字(注意是字符串)
var methodName=instanceInterface.methods[j];
//object[key]就是方法
if(!object[methodName]||typeof object[methodName]!=='function'){
throw new Error("the method name'"+methodName +"'is not found!");
}
}
}
}
var c1=new CompositeImp1();
Interface.ensureImplements(c1,CompositeInterface,FormItemInterface);
c1.add();
</script>