js20---接口3种方式

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Untitled Document</title>
        <script type=text/javascript charset=utf-8>
        //javascript没有定义接口的概念,我们通过模拟高级程序语言的方式来创建javascript中的接口。实现要重写接口所有的方法。
        /* javascript定义接口有三种方式
        1 注释描述接口
        2 属性检测接口
        3 鸭式辩型接口
        */

        // 1 注解描述的方式(注释方式,假的)
        /**
        interface Composite {
            function add(obj);
              function remove(obj);
             function uopdate(obj);
        }

        var CompositeImpl = function(){
            this.add = function(){},
            this.remove = function(){},
            this.upload = function(){}
        };
        var c1 = new CompositeImpl();
        var c2 = new CompositeImpl();
        alert(c1.add == c2.add); //false,每次都有一个add,所以写到原型里面
        */

        // CompositeImpl implements Composite
        var CompositeImpl = function(){
        };

        CompositeImpl.prototype.add = function(obj){
        }
        CompositeImpl.prototype.remove = function(obj){
        }
        CompositeImpl.prototype.update = function(obj){
        }

        var c1 = new CompositeImpl();
        var c2 = new CompositeImpl();
        alert(c1.add == c2.add);
        </script>
    </head>
    <body>
    </body>
</html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Untitled Document</title>
        <script type=text/javascript charset=utf-8>
        // 第二种实现接口的方式 属性检测的方式(继承接口,就要实现所有方法。)
        /**
         *     interface Composite {
         *         function add(obj);
         *         function remove(obj);
         *        function uopdate(obj);
         *  }
         *
         *  interface FormItem {
         *      function select(obj);
         *  }
         *
         */        

         // CompositeImpl implements Composite , FormItem
         var CompositeImpl = function(){
            // 显示的再类的内部 接受所实现的接口
            // 一般来说是一个规范 我们项目经理:在类的内部定义一个数组(名字要固定)
            this.implementsInterfaces = [‘Composite‘ ,‘FormItem‘ ];//this是这个类的当前对象
         }    

        CompositeImpl.prototype.add = function(obj){
            alert(‘add...‘);
        }
        CompositeImpl.prototype.remove = function(obj){
        }
        CompositeImpl.prototype.update = function(obj){
        }
        CompositeImpl.prototype.select = function(obj){
        }        

        // 检测CompositeImpl类的对象的
        function CheckCompositeImpl(instance){
            //判断当前对象是否实现了所有的接口
            if(!IsImplements(instance,‘Composite‘,‘FormItem‘)){
                throw new Error(‘Object does not implement a required interface!‘);
            }
        }

        function IsImplements(object){//实参多个,形参一个,这个形参就是实参的第一个,
            // arguments 对象 获得函数的实际参数
            for(var i = 1 ; i < arguments.length;i++){
                //接受所实现的每一个接口的名字
                var interfaceName = arguments[i];//arguments[i]在不在object.implementsInterfaces里面
                var interfaceFound = false ;
                for(var j = 0 ; j <object.implementsInterfaces.length;j++){
                        if(object.implementsInterfaces[j] == interfaceName)    {
                            interfaceFound = true ;
                            break;//跳出for循环
                        }
                }
                if(!interfaceFound){
                    return false ;
                }
            }
            return true ;
        }

        var c1 = new CompositeImpl();
        CheckCompositeImpl(c1);
        c1.add();
        </script>
    </head>
    <body>
    </body>
</html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Untitled Document</title>
        <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 arguments 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]);
            }
        }

        // 1 实例化接口对象
        var CompositeInterface = new Interface(‘CompositeInterface‘ , [‘add‘ , ‘remove‘]);//CompositeInterface对象有属性name为CompositeInterface,数组[‘add‘ , ‘remove‘]
        var FormItemInterface  = new Interface(‘FormItemInterface‘ , [‘update‘,‘select‘]);
        //  CompositeImpl implements CompositeInterface , FormItemInterface
        var CompositeImpl = function(){
        }
        // 3 实现接口的方法implements methods
        CompositeImpl.prototype.add = function(obj){
            alert(‘add‘);
        }
        CompositeImpl.prototype.remove = function(obj){
            alert(‘remove‘);
        }
        CompositeImpl.prototype.update = function(obj){
            alert(‘update‘);
        }
        /*
        CompositeImpl.prototype.select = function(obj){
            alert(‘select‘);
        }
        */

        // 三:检验接口里的方法
        Interface.ensureImplements = function(object){
            // 如果检测方法接受的参数小于2个 参数传递失败!
            if(arguments.length < 2 ){
                throw new Error(‘Interface.ensureImplements method constructor 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];
                    if( !object[methodName] || typeof object[methodName] !== ‘function‘ ){
                        throw new Error("the method name ‘" + methodName + "‘ is not found !");
                    }
                }
            }
        }

        var c1 = new CompositeImpl();
        Interface.ensureImplements(c1,CompositeInterface,FormItemInterface);
        c1.add();
        </script>
    </head>
    <body>
    </body>
</html>
var CompositeImpl = function(){}
CompositeImpl.prototype.add = function(obj){
    alert(‘add‘);
}

var c1 = new CompositeImpl();
alert(c1[‘add‘]);//function(obj){alert(‘add‘);}
alert(c1[‘ssadd‘]);//undefined
alert(c1[‘sss‘]);//undefined,
alert(c1.ssadd());//ssadd is not a function
alert(c1.sss);//undefined,  没有属性,方法,通过中括号返回未定义,就是假
c1[‘add‘];//什么都没有
alert(typeof c1[‘add‘]);//function

if( !c1[methodName] || typeof c1[methodName] !== ‘function‘ ){
    throw new Error("the method name ‘" + methodName + "‘ is not found !");
}// c1[methodName]有可能是一个属性,不是方法。  !==

// 判断对象是不是一个类的实例,判断对象的构造器是不是类名字
instanceInterface.constructor !== Interface
时间: 2024-12-11 12:16:44

js20---接口3种方式的相关文章

调用HTTP接口两种方式Demo

本Demo大部分参考原著:http://www.jianshu.com/p/cfdaf6857e7e 在WebApi发布之前,我们都是通过WebRequest/WebResponse这两个类组合来调用HTTP接口的 封装一个RestClient类 using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Text; using

创建线程的两种方式

首先我们需要知道什么是线程:是程序执行流的最小单元,包括就绪.阻塞和运行三种基本状态. 举个简单的例子:我们把生活中的两件事吃饭和写作业当作是两个线程,当你正在写作业的时候,爸妈叫你吃饭,你就直接去了,等吃完饭回来后再接着写作业.这就是相当于两个线程其中一个从运行状态转入就绪状态,另一个线程从就绪状态转入运行状态. 创建线程包括继承Thread类和实现Runnable接口两种方式(JDK5.0以后还包括了实现Callable等方式来实现线程,这里不做介绍,感兴趣的小伙伴可以自己查资料),下面介绍

创建对象的第二种方式:克隆clone,要实现Cloneable接口

1 ackage com.wisezone.clone; 2 3 /** 4 * 空接口: 5 * 标识,告诉JVM,通行 6 * 1.克隆 7 * 2.序列化 8 * 9 * 创建对象的第二种方式:克隆clone,要实现Cloneable 10 * @author 王东海 11 * @2017年4月15日 12 */ 13 public class TestClone implements Cloneable 14 { 15 public String name; 16 17 public s

JAVA中Arrays.sort()使用两种方式(Comparable和Comparator接口)对对象或者引用进行排序

一.描述 自定义的类要按照一定的方式进行排序,比如一个Person类要按照年龄进行从小到大排序,比如一个Student类要按照成绩进行由高到低排序. 这里我们采用两种方式,一种是使用Comparable接口:让待排序对象所在的类实现Comparable接口,并重写Comparable接口中的compareTo()方法,缺点是只能按照一种规则排序. 另一种方式是使用Comparator接口:编写多个排序方式类实现Comparator接口,并重写新Comparator接口中的compare()方法,

深入分析:Fragment与Activity交互的几种方式(三,使用接口)

第一步:我们需要在Fragment中定一个接口,并确保我们的容器Activity实现了此接口: public interface onTestListener { public void onTest(String str); } @Override public void onAttach(Activity activity) { super.onAttach(activity); // 这个方法是用来确认当前的Activity容器是否已经继承了该接口,如果没有将抛出异常 try { mCal

Python调用API接口的几种方式

相信做过自动化运维的同学都用过API接口来完成某些动作.API是一套成熟系统所必需的接口,可以被其他系统或脚本来调用,这也是自动化运维的必修课. 本文主要介绍python中调用API的几种方式,下面是python中会用到的库. - urllib2 - httplib2 - pycurl - requests urllib2 import urllib2, urllib github_url = 'https://api.github.com/user/repos' password_manage

06.实现servlet的几种方式,以及接口或者类之间的关系

接口:Servlet.ServletConfig.ServletRequest.ServletResponse.HttpServletRequest.HttpServletResponse.ServletContext 类:HttpServlet(抽象类).GenericServlet(抽象类) 来张关系图 ServletContext: ServletContext的对象是application是在项目初始化时被创建的.故servletContext随着应用初始化而被创建,随着应用的结束而被销

8.13.2 TreeSet实现Comparable接口的两种方式

推荐使用第二种方式,编写比较器可以使数据类的程序耦合度降低,同时比较器也可以重复利用! 第一种方式:数据类实现Comparable接口,实现其中的compareTo方法 创建对象时,使用TreeSet的默认构造函数! SortedSet users = new TreeSet(); class User implements Comparable{ //String name; int age; User(int age){ this.age = age; } public String toS

Java创建线程的第二种方式:实现runable接口

/*需求:简单的卖票程序多个窗口买票 创建线程的第二种方式:实现runable接口 *//*步骤1.定义类实现Runable接口2.覆盖Runable接口中的run方法    将线程要运行的代码存放在该run方法中 3.通过Thread类建立线程对象4.将Runable接口的子类对象作为实际参数传递给Thread类的构造函数  为什么要将Runable接口的子类对象传递给Thread的构造函数.  因为,自定义的run方法所属的对象是Runable接口的子类对象  所以要让线程去指定对象的Run

android回调接口的两种方式

熟悉MS-Windows和X Windows事件驱动设计模式的开发人员,通常是把一个方法的指针传递给事件源,当某一事件发生时来调用这个方法(也称为“回调”).Java的面向对象的模型目前不支持方法指针,似乎不能使用这种方便的机制. 但是java本身拥有interface,我们可以用interface实现相同的效果.在android中,如果我们需要对一个button的点击事件往外传,可以有两种实现方式. 第一种方式的大体步骤是: 1.定义一个回调接口,用来捕捉和“存放”点击事件. public i