JavaScript 实现接口 (Interfaces In JavaScript)

接口是面向对象编程里的重要特性,遗憾的是JavaScript并没有提供对接口的支持!怎么实现接口呢?

在实际中,我们可以在注释中定义好接口,在实际的代码中予以实现

比如:

/*
interface Composite {
    function add(child);
    function remove(child);
    function getChild(index);
}
interface FormItem {
    function save();
}
*/
var CompositeForm = function(id, method, action) { // implements Composite, FormItem
...
};
// Implement the Composite interface.
CompositeForm.prototype.add = function(child) {
...
};
CompositeForm.prototype.remove = function(child) {
...
};
CompositeForm.prototype.getChild = function(index) {
...
};
// Implement the FormItem interface.
CompositeForm.prototype.save = function() {
...
};

实现接口的程序员是否将这些接口都实现了呢?我们没办法保证!因为这里没有任何办法去检查是否都实现了

我们需要一个检查是否实现了接口的机制,可以这样:

/*
interface Composite {
    function add(child);
    function remove(child);
    function getChild(index);
}
interface FormItem {
    function save();
}
*/
var CompositeForm = function(id, method, action) {
    this.implementsInterfaces = ['Composite', 'FormItem'];
...
};
...
function addForm(formInstance) {
    if(!implements(formInstance, 'Composite', 'FormItem')) {
        throw new Error("Object does not implement a required interface.");
    }
...
}
// The implements function, which checks to see if an object declares that it
// implements the required interfaces.
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.
}

这种方法让程序员在写的时候注明实现了哪些接口: this.implementsInterfaces = ['Composite', 'FormItem']; 在调用的时候使用implements方法来判断是否实现了,理论上可行,很有可能写上了实现了'Composite'接口,但是代码里却并没有add方法!因此,我们需要检验实现接口的类是否包含了接口里的方法!所以,接口必须从注释中解放出来:

// Interfaces.
var Composite = new Interface('Composite', ['add', 'remove', 'getChild']);
var FormItem = new Interface('FormItem', ['save']);
// CompositeForm class
var CompositeForm = function(id, method, action) { // implements      Composite, FormItem
...
};
...
function addForm(formInstance) {
    Interface.ensureImplements(formInstance, Composite, FormItem);
    // This function will throw an error if a required method is not implemented,
    // halting execution of the function.
    // All code beneath this line will be executed only if the checks pass.
...
}

    定义接口Composite,FormItem,并且CompositeForm实现这两个接口,在使用的时候,用Interface.ensureImplements来检验formInstance是否实现了这两个接口中的所有方法。

来看看Interface的定义:两个参数,第一个参数是接口名称,第二个参数是接口包含的方法数组

// Constructor.
var Interface = function(name, methods) {
    if(arguments.length != 2) {
        throw new Error("Interface constructor called with " + arguments.length +
"arguments, but expected exactly 2.");
}
    this.name = name;
    this.methods = [];
    for(var i = 0, len = methods.length; i < len; i++) {
        if(typeof methods[i] !== 'string') {
            throw new Error("Interface constructor expects method names to be "
+ "passed in as a string.");
        }
    this.methods.push(methods[i]);
    }
};

为Interface 添加建议接口是否实现的静态方法

// Constructor.
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.");
        }
    }
    }
};

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏我就是马云飞

Retrofit源码模拟

如果要进行网络请求,你可能会这样写一个简单的OKHttp请求 public class CallExector { public static fin...

239100
来自专栏Golang语言社区

动手实现一个JSON验证器(上)

分析 既然要验证JSON的有效性,那么必然需要清楚的知道JSON格式,这个在JSON官网已经给我们画出来了: ? ? ? ? ? 从官方的图上面可以看出,JSO...

53870
来自专栏向治洪

ES7、ES8新特性

概述 JavaScript,作为一门处于高速发展期的开发语言,正在变的越来越完善、稳定。我们必须拥抱这些变化,并且我们需要把ES8加入到我们的技术栈中。 E...

1.9K50
来自专栏技术博客

Asp.Net Web API 2第十三课——ASP.NET Web API中的JSON和XML序列化

阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.h...

17630
来自专栏Java面试通关手册

Java多线程学习(二)synchronized关键字(2)

Java面试通关手册(Java学习指南,欢迎Star,会一直完善下去,欢迎建议和指导):https://github.com/Snailclimb/Java_G...

23860
来自专栏向治洪

ES7和ES8新特性介绍

概述 JavaScript,作为一门处于高速发展期的开发语言,正在变的越来越完善、稳定。我们必须拥抱这些变化,并且我们需要把ES8加入到我们的技术栈中。 ECM...

69660
来自专栏菩提树下的杨过

java一些常用并发工具示例

最近把《java并发编程实战》-Java Consurrency in Practice 重温了一遍,把书中提到的一些常用工具记录于此: 一、闭锁(门栓)- C...

24670
来自专栏xx_Cc的学习总结专栏

iOS底层原理总结 - 探寻Runtime本质(三)

14420
来自专栏difcareer的技术笔记

JNI实现源码分析【四 函数调用】正文0x01:dvmCallMethodV0x02:nativeFunc0x03: 何时赋值

有了前面的铺垫,终于可以说说虚拟机是如何调用JNI方法的了。JNI方法,对应Java中的native方法,所以我们跟踪对Native方法的处理即可。

11540
来自专栏大内老A

WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer)

大部分的系统都是以数据为中心的(Data Central),功能的实现表现在对相关数据的正确处理。而数据本身,是有效信息的载体,在不同的环境具有不同的表示。一个...

36380

扫码关注云+社区

领取腾讯云代金券