Javascript中如何实现interface机制
我们知道,ECMAScript中是没有interface⼀说的。虽然如此,参考《Pro Javascript Design Pattern》⼀书,哥算是到⽅案了。
最简单的⽅案,就是通过⽂档说明了。简称⽅案1,代码如下:
/*
interface composite{
function add(child);
function remove(child);
function getChild(index);
}
interface formItem{
function save();
}
*/
var compositeForm = function (id, name) {
this.id = id;
this.name = name;
if (typeof (compositeForm._initialized) === "undefined") {
// implement the composite interface.
compositeForm.prototype.add = function (child) {
console.log("added.");
};
ve = function (child) {
console.log("removed.");
};
Child = function (index) {
return "Here is a child.";
};
// implement the formItem interface.
compositeForm.prototype.save = function () {
console.log("saved.");
};
compositeForm._initialized = true;
}
};
这种⽅案⾥,通过js的伪代码,定义好composite和formItem 2个接⼝,然后在compositeForm 类中通过动态原型来实现接⼝中定义的⽅法。以下是简单的⼏⾏测试代码:
var item = new compositeForm(1, "form 1");
console.log(item.id);
item.add(null);
item.save();
var item2 = new compositeForm(2, "form 2");
console.log(item.add == item2.add);
对于具有特强执⾏⼒和完全可控制的团队来说,完全没有问题。问题是,21世纪有这样的团队吗?即便有,IT圈⾥的⼈员变动也不能保证它⼀如既往啊。改进的⽅案就是,通过约定和校验了。作出改进(简称⽅案2),详细如下:
/
*
interface composite{
function add(child);
function remove(child);
function getChild(index);
}
interface formItem{
function save();
}
*/
var compositeForm = function (id, name) {
this.id = id;
this.name = name;
if (typeof (compositeForm._initalized) === "undefined") {
// implement the composite interface.
compositeForm.prototype.add = function (child) {
console.log("added.");
};
ve = function (child) {
console.log("removed.");
};
Child = function (index) {
return "Here is a child.";
};
// implement the formItem interface.
compositeForm.prototype.save = function () {
console.log("saved.");
};
//sign for implemented interfaces
compositeForm.prototype.implementsInterfaces = ["composite", "formItem"];
compositeForm._initalized = true;
}
};
function implements(obj, interfaces) {
if (obj == null || typeof (obj) !== "object") {
throw new Error("obj must to be a object.");
}
if(interfaces == null || !(interfaces instanceof Array)){
throw new Error("interfaces must to be a Array");
}
for(item in interfaces){
if(typeof(interfaces[item]) !== "string"){
throw new Error("interfaces must to be a string Array");
}
}
var result = true;
if (interfaces.length > 0) {
if (typeof (obj.implementsInterfaces) === "undefined" || !
(obj.implementsInterfaces instanceof Array) || obj.implementsInterfaces.length < 1) {            result = false;
} else {
for (item in interfaces) {
var itemResult = false;
for (funIndex in obj.implementsInterfaces) {
if (interfaces[item] == obj.implementsInterfaces[funIndex]) {
itemResult = true;
break;
}
}
if (!itemResult) {
result = false;
break;
}
}
return result;
}
// Validate instace. If invalid, throw exception.
function addForm(formInstance) {
if (!implements(formInstance, ["composite", "formItem"])) {
throw new Error("Object doesn't implement the interfaces.");
}
//...
}
它的核⼼就是:compositeForm.prototype.implementsInterfaces = ["composite", "formItem"];通过定义implementsInterfaces属性,并将它赋值为已实现的接⼝名称的数组。⽽implements⽅法就是通过对⽐对象实体的implementsInterfaces属性和需要实现的接⼝名称逐⼀进⾏对⽐,来判断实体所属类是否真的实现了指定接⼝。但是,如果给implementsInterfaces赋值说已实现了某接⼝,但是并没有实现它的⽅法,怎么办?
继续改进,有⽅案3:
/*
interface composite{
function add(child);
function remove(child);
function getChild(index);
}
interface formItem{
function save();
}
*/
// interface class
var Interface = function (name, methods) {
if (arguments.length != 2) {
throw new Error("Interface constructor called with " + arguments.length + "arguments, but expected exactly 2.");
}
if (typeof name !== "string") {
throw new Error("Interface constructor expected name to be passed in as a string.");
}
if (methods == null || !(methods instanceof Array)) {
throw new Error("Interface constructor expected methods to be passed in as a method.");
}
this.name = name;
};
if (arguments.length != 2) {typeof array
throw new Error("sureImplements called with " + arguments.length + "arguments, but expected 2.");
}
if (classFun == null || typeof (classFun) != "object") {
throw new Error("classFun expected to be passed in a object.");
}
if (interfaces == null || !(interfaces instanceof Array)) {
throw new Error("interfaces expected to be passed in a Array.");
}
for (index in interfaces) {
if (!(interfaces[index] instanceof Interface)) {
throw new Error("interfaces[" + index + "] expected to be passed in a Interface.");
}
var currentInterface = interfaces[index];
for (methodIndex hods) {
var methodName = hods[methodIndex];
if (!classFun[methodName] || typeof (classFun[methodName]) != "function") {
return false;
}
return true;
};
// define two interfaces
var compsite = new Interface("compsite", ["add", "remove", "getChild"]);
var formItem = new Interface("formItem", ["save"]);
// a class implements above two interfaces
var compositeForm = function (id, name) {
this.id = id;
this.name = name;
if (typeof (compositeForm._initialized) === "undefined") {
// implement the composite interface.
compositeForm.prototype.add = function (child) {
console.log("added.");
};
ve = function (child) {
console.log("removed.");
};
Child = function (index) {
return "Here is a child.";
};
// implement the formItem interface.
compositeForm.prototype.save = function () {
console.log("saved.");
};
compositeForm._initialized = true;
}
};
// Validate instace. If valid, alert true. Else, throw exception.
function addForm(formInstance) {
if (!sureImplements(formInstance, [compsite, formItem])) {
throw new Error("Object doesn't implement the interfaces.");
}
//...
alert('true');
}
这⾥定义了Interface类,并实现了类的ensureImplements静态⽅法。关于Interface类的实现,可以独⽴作为⼀个⽂件,以后多个地⽅可以⽤到。然后,通过下⾯的代码来定义接⼝:
var compsite = new Interface("compsite", ["add", "remove", "getChild"]);
var formItem = new Interface("formItem", ["save"]);
⾄于compositeForm类⾃⾝的实现,除了不再需要implementsInterfaces签名,其他和之前的⼏乎⼀样。使⽤时,通过调⽤:
if (!sureImplements(formInstance, [compsite, formItem])) {
throw new Error("Object doesn't implement the interfaces.");
}
来判断是否真的实现了指定接⼝。它不仅可以判断到接⼝,还可以判断到⽅法。
⾄此,不仅可以定义interface,还可以ensure implement了。 (注:以上⽅法主题思路来源于Pro Java
script Design Pattern,但同时修复了它⾥⾯的⼀些细⼩问题)完整代码

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。