JavaScript是弱类型语言,所以类型匹配问题很难追踪。同时,Js并没有像其他语言一样,提供内置的创建或实现接口的方法。这样,在我们进行对象转化的时候是很困难的。
不过,我们还是可以使用程序来模拟JavaScript Interface接口的实现。一般来说,模拟Interface的实现有如下三种方法:
注释法——将接口的定义写在注释中,大家能否小心注意,以实现接口的所有方法全凭自觉。
java中使用interface和implements关键字实现接口的
/* interface Composite{ function add(child); function remove(child); function getChild(index); } interface FormItem{ function save(); } */
//模拟CompositeForm继承了Composite、FormItem接口 var CompositeForm = function(id,name,action){ ... } CompositeForm.prototype = { add:function(child){ ... }, remove:function(child){ ... }, getChild:function(index){ ... }, save:function(){ ... } }
备注:这种模仿并不是很好,它没有为确保CompositeForm真正实现了正确的方法集而进行检查,也不会抛出错误以告知程序中有问题。
属性检查法——自己说明我实现了哪些接口,一会儿你检查的时候记得检查我说我实现的接口里面,是否把我真正想要实现的接口全部实现了(这么别扭呢),总之就是自欺欺人
var CompositeForm = function(id, method, action) { //声明自己继承了Composite,FormItem接口 this.implementsInterfaces = ['Composite', 'FormItem']; ... }; function addForm(formInstance) { //判断formInstance是否继承了Composite,FormItem接口 if(!implements(formInstance, 'Composite', 'FormItem')) { throw new Error("Object does not implement a required interface."); } ... } //判断当前对象是否继承了对象声明的接口 function implements(object) { for(var i = 1; i < arguments.length; i++) { // Looping through all arguments // after the first one. var interfaceName = arguments[i]; var interfaceFound = false; for(var j = 0; j < object.implementsInterfaces.length; j++) { if(object.implementsInterfaces[j] == interfaceName) { interfaceFound = true; break; } } if(!interfaceFound) { return false; // An interface was not found. } } return true; // All interfaces were found. }
鸭式辨型法——如果对象具有与接口定义的方法同名的所有方法,那么久可以认为它实现了这个接口。
var Interface = function(name,methods){ if(arguments.length!=2){ throw new Error("Interface 的构造函数一定只能有两个参数") } this.name = name; this.methods = []; for(var i=0,len=methods.length;i<len;i++){ if(typeof methods[i] !== "string"){ throw new Error("Interface构造参数方法名称为string类型"); }else{ this.methods.push(methods[i]); } } } Interface.ensureImplements = function(object){ //至少包含两个参数——继承接口的对象,对应的接口(至少含有一个) if(arguments.length<2){ throw new Error("Function Interface.ensureImplements called with " + arguments.length + "arguments, but expected at least 2."); } for(var i=1,len=arguments.length;i<len;i++){ //具体实现接口的对象 var _interface = arguments[i]; if(_interface.constructor !== Interface) { throw new Error("Function Interface.ensureImplements expects arguments " + "two and above to be instances of Interface."); } //接口对应的参数 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("Function Interface.ensureImplements: object " + "does not implement the " + _interface.name + " interface. Method " + method + " was not found."); } } } } var Composite = new Interface("Composite",["add","remove","getChild"]); var FormItem = new Interface("FormItem",["save"]); //CompositeForm继承Composite、FormItem两个接口 /*提示缺少接口对象参数 var CompositeForm = new function(id, method, action){ } Interface.ensureImplements(CompositeForm); */ /*提示没有实现Composite接口 var CompositeForm = new function(id, method, action){ } Interface.ensureImplements(CompositeForm,Composite); */ /*提示没有实现Composite接口 var CompositeForm = new function(id, method, action){ this.add=function(){}; this.remove=function(){}; //this.getChild=function(){}; } Interface.ensureImplements(CompositeForm,Composite); */ /*正确显示 var CompositeForm = new function(id, method, action){ this.add=function(){}; this.remove=function(){}; this.getChild=function(){}; } Interface.ensureImplements(CompositeForm,Composite); */ /* var CompositeForm = new function(id, method, action){ this.add=function(){}; this.remove=function(){}; this.getChild=function(){}; this.save=function(){}; } Interface.ensureImplements(CompositeForm,Composite,FormItem); */ var CompositeForm = new function(id, method, action){ this.add=function(){}; this.remove=function(){}; this.getChild=function(){}; this.save=function(){}; //用来验证当前对象是否实现了Composite,FormItem接口 Interface.ensureImplements(this,Composite,FormItem); }
教程上的另外一个例子
ResultFormatter.prototype.renderResults = function() { var dateOfTest = this.resultsObject.getDate(); var resultsArray = this.resultsObject.getResults(); var resultsContainer = document.createElement('div'); var resultsHeader = document.createElement('h3'); resultsHeader.innerHTML = 'Test Results from ' + dateOfTest.toUTCString(); resultsContainer.appendChild(resultsHeader); var resultsList = document.createElement('ul'); resultsContainer.appendChild(resultsList); for(var i = 0, len = resultsArray.length; i < len; i++) { var listItem = document.createElement('li'); listItem.innerHTML = resultsArray[i]; resultsList.appendChild(listItem); } return resultsContainer; }; // ResultSet Interface. var ResultSet = new Interface('ResultSet', ['getDate', 'getResults']); // ResultFormatter class, after adding Interface checking. var ResultFormatter = function(resultsObject) { Interface.ensureImplements(resultsObject, ResultSet); this.resultsObject = resultsObject; };