zoukankan      html  css  js  c++  java
  • 01.Javascript中的接口Interface [转载]

    转载地址:http://blog.csdn.net/ymmc001/archive/2010/11/05/5990021.aspx

    本文主要讲述如何用原生的Javascript代码来模拟并实现接口

    前言

    众所周知,在Java、C#等语言中,接口由专门的关键字interface来定义,而接口的实现则有implements关键字来完成,接口有什么特点呢?简单地说有(不完全归纳):

    1. 不可被实例化
    2. 所有方法都是抽象方法
    3. 所有属性都是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方法,就是这个方法了,请务必留意,谢谢。

  • 相关阅读:
    WPF 使用 Direct2D1 画图 绘制基本图形
    WPF 使用 Direct2D1 画图 绘制基本图形
    dot net core 使用 IPC 进程通信
    dot net core 使用 IPC 进程通信
    win2d 图片水印
    win2d 图片水印
    Java实现 LeetCode 240 搜索二维矩阵 II(二)
    PHP closedir() 函数
    PHP chroot() 函数
    PHP chdir() 函数
  • 原文地址:https://www.cnblogs.com/jsfans/p/1909349.html
Copyright © 2011-2022 走看看