大家好!今天跟大家一起分享我的OOP框架YOOP重构实践,希望能与大家一起共同学习、共同进步。

本文展示了我对没有编写测试的YOOP原始版本的重构过程。通过该重构,力图将一个杂乱无章的遗留代码重构为有良好测试的、结构良好、可读性较强的高质量代码。

在本次重构中,我不但会对代码结构进行重构,还会改变部分行为(如将“抽象类要检查是否实现了接口成员和父类的抽象方法”修改为“抽象类不检查是否实现了接口成员和父类的抽象方法”;将“抽象类、类只能继承1个接口”修改为“可以继承多个接口”等等)。改变行为时,必须先添加或者修改测试,然后才能小步地改变行为。

原始版本

(function () {

    /************************************************** String对象扩展 ***********************************************************
    
    扩展方法:
    contain
    containIgnoreCase
    trim

    */
    if (!String.prototype.contain) {
        String.prototype.contain = function (str) {
            /* 使用RegExp对象来构造动态匹配。
            注意!str是字符串,因此需要转义!

            由于JavaScript字符串中的“\”是一个转义字符,因此,使用显式构造函数创建RegExp实例对象时,应将原始正则表达式中的“\”用“\\”替换。例如,在代码1.2中的两条语句是等价的。

            代码1.2   转义字符中的“\”:1.2.htm

            <script language="javascript">

            var re1 = new RegExp("\\d{5}");

            var re2 = /\d{5}/;

            alert("re1="+re1+"\nre2="+re2);

            </script>

         

            由于正则表达式模式文本中的转义字符也是“\”,如果正则表达式中要匹配原义字符“\”,在正则表达式模式文本中要以“\\”来表示,当使用显式构造函数的方式创建RegExp实例对象的时候,就需要使用“\\\\”来表示原义字符“\”。

            var re = new RegExp(\\\\)。

            */
            var reg = new RegExp(str);
            if (this.match(reg)) {  //用this指针指代本体
                return true;
            }
            else {
                return false;
            }
        }
    }

    /*****************************************************************************************************************************/


    //当前是否处于创建类的阶段。
    //放在自执行函数中,initializing就是自执行函数的内部变量,自执行函数的上下文结束后,外部就不能访问initializing了。
    //不用var的话,就不是当前上下文的一个变量了,而是全局对象的一个属性。这样外部就能够访问了。
    var initializing = false;
    //    var count = 0;


    //获得函数的参数数组
    function argumentNames(fn) {
        var names = fn.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1].replace(/\s+/g, '').split(',');
        return names.length == 1 && !names[0] ? [] : names;
    };

    /* 深拷贝
    */
    function extendDeep(parent, child) {
        var i,
                toStr = Object.prototype.toString,
                sArr = "[object Array]",
                sOb = "[object Object]",
                type = "",
        child = child || {};

        for (i in parent) {
            //if (parent.hasOwnProperty && parent.hasOwnProperty(i)) {

            //                if (typeof parent[i] === 'object') {    //null === 'object'也为true!

            type = toStr.call(parent[i]);
            if (type === sArr || type === sOb) {    //如果为数组或object对象
                child[i] = type === sArr ? [] : {};
                extendDeep(parent[i], child[i]);
            } else {
                child[i] = parent[i];
            }
        }
        //}
        return child;
    };


    //获得函数名
    function getFunctionName(fn) {
        var name = "";

        if (!fn) {
            return null;
        }

        name = fn.toString().match(/^.*function\s*([^\(]*)/);
        return name === null ? name : name[1];
    };

    //判断是否为数组
    function isArray(val) {
        return Object.prototype.toString.call(val) === "[object Array]";
    };

    //检查抽象类的公有方法+虚方法+抽象方法是否包含父类的抽象方法/属性 或 接口方法/属性。
    //不用hasOwnProperty判断!否则就检查不到是否包含了父类的抽象方法/属性 或 接口方法/属性。
    function check(parentClass, interface, children) {
        //        if (!parent || !interface || !children) {
        //            throw new Error("check - arguments error!");
        //        }

        var name = "";

        if (parentClass) {
            //检查是否实现了抽象方法/属性
            for (name in parentClass.prototype) {
                if (parentClass.prototype.hasOwnProperty(name)) {
                    //                console.log(name);
                    if (name === "constructor") {
                        continue;
                    }
                    if (name.contain("Abstract_")) {
                        //抽象方法
                        if (typeof parentClass.prototype[name] === "function") {
                            if (children[name.slice(9)] === undefined || typeof children[name.slice(9)] !== "function") {
                                //                            var t = name.slice(9);
                                throw new Error("Abstract method '" + name + "' must be overwrited!");
                            }
                        }
                            //抽象属性
                        else {
                            if (children[name.slice(9)] === undefined || typeof children[name.slice(9)] === "function") {
                                //                            var t = name.slice(9);
                                //                            var p = children[name.slice(9)];
                                //                            var q = typeof children[name.slice(9)];
                                throw new Error("Abstract attribute '" + name + "' must be overwrited!");
                            }
                        }
                    }
                }
            }
        }

        if (!interface) {
            return;
        }

        //检查是否实现了接口方法/属性
        for (name in interface.prototype) {
            //                console.log(name);
            if (name === "constructor") {
                continue;
            }
            //                if (interface.prototype.hasOwnProperty(name)) {
            //接口方法
            if (typeof interface.prototype[name] === "function") {
                //                    var t = name.slice(10);
                //                    var m = children[name.slice(10)];
                //                        console.log("t = " + t);
                //                        console.log("m = " + m);
                if (children[name.slice(10)] === undefined || typeof children[name.slice(10)] !== "function") {
                    throw new Error("Interface method '" + name + "' must be overwrited!");
                }
            }
                //接口属性
            else {
                //                    var t = name.slice(10);
                //                    var m = children[name.slice(10)];
                //                        console.log("t = " + t);
                //                        console.log("m = " + m);
                if (children[name.slice(10)] === undefined || typeof children[name.slice(10)] === "function") {
                    throw new Error("Interface attribute '" + name + "' must be overwrited!");
                }
            }
            //                }
        }
    };

    //检查抽象成员
    function addAbstract(abstract, currentClass, temp) {
        var name = "";

        for (name in abstract) {
            if (abstract.hasOwnProperty(name)) {
                //                if (typeof abstract[name] !== "function") {
                //                    throw new Error("Virtual attribute is not allowed!");
                //                }
                //                else {
                //抽象方法前面加"Abstract_"前缀
                currentClass.prototype["Abstract_" + name] = abstract[name];
                //                currentClass.prototype[name] = abstract[name];

                temp[name] = abstract[name];    //加入temp
                //                }
            }
        }
    };

    //检查虚方法(不能为虚属性)
    function addVirtual(virtual, currentClass, temp) {
        var name = "";

        for (name in virtual) {
            if (virtual.hasOwnProperty(name)) {
                if (typeof virtual[name] !== "function") {
                    throw new Error("Virtual attribute is not allowed!");
                }
                else {
                    currentClass.prototype[name] = virtual[name];

                    temp[name] = virtual[name];    //加入temp
                }
            }
        }
    };

    //加入密封方法。
    //没有实现检查子类是否重写了父类的密封方法,只是定义了一个规范。
    function addSealed(sealed, currentClass, temp) {
        var name = "";

        for (name in sealed) {
            if (sealed.hasOwnProperty(name)) {
                currentClass.prototype[name] = sealed[name];

                temp[name] = sealed[name];    //加入temp
            }
        }
    };

    //获得在原型prototype中不存在同名的str。
    //如果有同名,则加上前缀"_"
    function getNoRepeatStrInPrototype(prototype, str) {
        var new_str = "";

        if (!prototype[str]) {
            return str;
        }

        new_str = "_" + str;
        return getNoRepeatStrInPrototype(prototype, new_str);
    }




    //创建接口
    //接口可以继承接口
    function MyInterface(_parent, _method, _attribute) {
        var i = 0, args = null;

        var parent = null,
            method = null,
            attribute = null;

        if (typeof _parent === "function") {
            if (getFunctionName(_parent) !== "I") {
                throw new Error("Interface must inherit interface!");
            }
            else {
                parent = _parent;

                //形如“MyInterface(Parent, "A", "B", "GetName");”
                if (_method && !isArray(_method)) {
                    method = Array.prototype.slice.call(arguments, 1);
                    attribute = null;
                }
                    //形如“MyInterface(Parent, ["A", "B", "GetName"], ["a", "c"]);”
                else {
                    method = _method;
                    attribute = _attribute;
                }
            }
            //            console.log(parent.toString());
        }
        else {
            parent = null;
            //形如“MyInterface("A", "B", "GetName");”
            if (_method && !isArray(_method)) {
                method = arguments
                attribute = null;
            }
                //形如“MyInterface(["A", "B", "GetName"], ["a", "c"]);”
            else {
                method = arguments[0];
                attribute = arguments[1];
            }
        }

        function I() {
        }

        // 如果此接口需要从其它接口扩展
        if (parent) {
            I.prototype = new parent();
            I.prototype.constructor = I;
        }

        //        console.log("method = " + method);
        //        console.log("attribute = " + attribute);


        //        //形如“MyInterface(["A", "B", "GetName"], ["a", "c"]);”
        //        if (isArray(method)) {

        //方法
        for (i = 0; i < method.length; i++) {
            //加上前缀“Interface_”
            I.prototype["Interface_" + method[i]] = function () {
                throw new Error("This method must be overwrited!");
            };
        }
        //属性
        if (attribute) {
            if (!isArray(attribute)) {
                throw new Error("Attribute must be array!");
            }
            else {
                for (i = 0; i < attribute.length; i++) {
                    //加上前缀“Interface_”
                    I.prototype["Interface_" + attribute[i]] = 0;
                }
            }
        }
        //        }
        //        //形如“MyInterface("A", "B", "GetName");”
        //        else {
        //            args = Array.prototype.slice.call(arguments, 1);
        //            //方法
        //            for (i = 0; i < args.length; i++) {
        //                I.prototype[args[i]] = function () {
        //                    throw new Error("This method must be overwrited!");
        //                };
        //            }
        //        }

        return I;
    };



    //创建抽象类
    //抽象类能够继承接口、抽象类以及实体类,但此处约定抽象类只能继承接口和抽象类,不能继承实体类!
    //(这样方便判断抽象类是否包含全部的父类(接口/抽象类)成员)
    function MyAbstract(_parent, _prop) {
        var Static = null;
        var k = null, name = null, temp = {},
            virtual = {};

        //        if (arguments.length > 1) {
        //            throw new Error("AbstractClass can't inherit other classes!");
        //        }

        var abstractClass = null,
                interface = null,
            prop = null;

        //原型恢复标志,用于防止第一次创建实例时恢复原型
        var mark_resume = false;


        //取出父类、接口
        if (arguments.length === 1) {
            prop = arguments[0];
            //            parent = null;
            abstractClass = null;
            interface = null;
        }
            //_parent为{Class: xx, Interface: xx}
        else if (typeof _parent === "object") {

            if (!_parent.Class && !_parent.Interface) {
                throw new Error("Please add AbstractClass or Interface!");
            }
            if (getFunctionName(_parent.Class) === "F" || getFunctionName(_parent.Interface) === "F") {
                throw new Error("AbstractClass here can't inherit parentClass which is created by MyClass function!");
            }

            abstractClass = _parent.Class;
            interface = _parent.Interface;

            prop = _prop;
        }
            //_parent直接为xx,就表示父类为抽象类
        else if (typeof _parent === "function") {
            if (getFunctionName(_parent) === "F") {
                throw new Error("AbstractClass here can't inherit parentClass which is created by MyClass function!");
            }

            abstractClass = _parent;
            interface = null;

            prop = _prop;
        }
        else {
            throw new Error("arguments is not allowed!");
        }


        Static = prop.Static ? prop.Static : null;


        // 本次调用所创建的类(构造函数)
        function A() {
            //            // 如果抽象父类存在,则实例对象的baseClass指向父类的原型
            //            // 这就提供了在实例对象中调用父类方法的途径
            //            if (abstractClass) {
            //                this.baseClass = abstractClass.prototype;
            //            }

            ////防止第一次创建实例时恢复原型
            //if (mark_resume) {
            //    //还原原型
            //    extendDeep(A.prototype.backUp_prototype, A.prototype);
            //}
            //else {
            //    mark_resume = true;
            //}

        }

        // 如果此接口需要从其它接口扩展
        if (abstractClass) {
            //            //删除父类的私有成员,保留本类的私有成员
            //            for (name in abstractClass.prototype) {
            //                if (abstractClass.prototype.hasOwnProperty(name)) {
            //                    //私有成员以“_”开头,可能有多个“_”(多层继承)
            //                    if (!name.match(/^_+/)) {
            //                        //                                                delete parentClass.prototype[name];
            //                        A.prototype[name] = abstractClass.prototype[name];
            //                    }
            //                }
            //            }

            //A.prototype = new abstractClass();
            A.prototype = extendDeep(abstractClass.prototype);

            A.prototype.constructor = A;

            // 如果父类存在,则实例对象的baseClass指向父类的原型。
            // 这就提供了在实例对象中调用父类方法的途径。
            //baseClass的方法是指向abstractClass的,不是指向F(子类)的!

            A.prototype[getNoRepeatStrInPrototype(abstractClass.prototype, "baseClass")] = abstractClass.prototype;
            //A.prototype.baseClass = abstractClass.prototype;
        }

        //加入构造函数
        //抽象类本身因为不能实例化,所以不调用构造函数。
        //抽象类中的构造函数供子类构造函数中调用。
        if (prop.Init) {
            if (abstractClass) {
                A.prototype.Init = function (name) {
                    return function () {
                        //此处不用创建闭包了!因为外面已经创建了闭包,name已经被保存了!
                        this.base = function () {
                            //这个写法也可以!为什么不用apply修正this也行??!
                            //parentClass.prototype[name](); 

                            //此处的arguments为base方法传入的形参
                            //注意!要加上“return”,这样才能返回parentClass.prototype[name]的返回值
                            return abstractClass.prototype[name].apply(abstractClass.prototype, arguments);
                        };
                        //指向子类,可以用于模版模式
                        this.baseToSubClass = abstractClass.prototype[name];

                        //执行fn并返回执行的结果
                        //此处的arguments为F.prototype[name]方法传入的形参。
                        return prop[name].apply(this, arguments);
                    };

                }("Init");
            }
            else {
                A.prototype.Init = prop.Init;
            }
        }

        if (prop.Private) {
            //私有属性/方法直接覆盖
            for (name in prop.Private) {
                if (prop.Private.hasOwnProperty(name)) {
                    A.prototype[name] = prop.Private[name];
                }
            }
        }

        if (prop.Public) {
            for (name in prop.Public) {
                if (prop.Public.hasOwnProperty(name)) {
                    //检查抽象成员,抽象成员放到Public或Protected中
                    if (name === "Abstract") {
                        addAbstract(prop["Public"][name], A, temp);
                        continue;
                    }
                    //检查虚方法,虚方法放到Public或Protected中
                    if (name === "Virtual") {
                        addVirtual(prop["Public"][name], A, temp);
                        continue;
                    }
                    //密封的方法(不允许子类重写)
                    if (name === "Sealed") {
                        addSealed(prop["Public"][name], A, temp);
                        continue;
                    }

                    if (abstractClass &&
            typeof prop.Public[name] === "function" &&
            typeof A.prototype[name] === "function") {
                        A.prototype[name] = function (name) {
                            return function () {
                                //此处不用创建闭包了!因为外面已经创建了闭包,name已经被保存了!
                                this.base = function () {
                                    //这个写法也可以!为什么不用apply修正this也行??!
                                    //parentClass.prototype[name](); 

                                    //此处的arguments为base方法传入的形参
                                    //注意!要加上“return”,这样才能返回parentClass.prototype[name]的返回值
                                    return abstractClass.prototype[name].apply(abstractClass.prototype, arguments);
                                };
                                //指向子类,可以用于模版模式
                                this.baseToSubClass = abstractClass.prototype[name];

                                //执行fn并返回执行的结果
                                //此处的arguments为F.prototype[name]方法传入的形参。
                                return prop.Public[name].apply(this, arguments);
                            };

                        }(name);
                    }
                    else {
                        A.prototype[name] = prop.Public[name];
                    }



                    temp[name] = prop.Public[name];    //用于检查是否包含父类的抽象方法/属性 或 接口方法/属性
                }
            }
        }
        //保护成员
        if (prop.Protected) {
            for (name in prop.Protected) {
                if (prop.Protected.hasOwnProperty(name)) {
                    //检查抽象成员,抽象成员放到Public或Protected中
                    if (name === "Abstract") {
                        addAbstract(prop["Protected"][name], A, temp);
                        continue;
                    }
                    //检查虚方法,虚方法放到Public或Protected中
                    if (name === "Virtual") {
                        addVirtual(prop["Protected"][name], A, temp);
                        continue;
                    }
                    //密封的方法(不允许子类重写)
                    if (name === "Sealed") {
                        addSealed(prop["Protected"][name], A, temp);
                        continue;
                    }
                    A.prototype[name] = prop.Protected[name];

                }
            }
        }





        //        //虚方法(不能为虚属性)
        //        if (prop.Virtual) {
        //            for (name in prop.Virtual) {
        //                if (prop.Virtual.hasOwnProperty(name)) {
        //                    if (typeof prop.Virtual[name] !== "function") {
        //                        throw new Error("Virtual attribute is not allowed!");
        //                    }
        //                    else {
        //                        //                        //虚方法前面加"Virtual_"前缀,在子类中要检查虚方法
        //                        A.prototype[name] = prop.Virtual[name];

        //                        temp[name] = prop.Virtual[name];    //用于检查是否包含父类的抽象方法/属性 或 接口方法/属性
        //                    }
        //                }
        //            }
        //        }


        //抽象类可以没有抽象成员
        //        if (!prop.Abstract) {
        //            throw new Error("AbstractClass must have abstract methods!");
        //        }

        //放到外面的抽象成员,默认为公有抽象成员
        for (name in prop.Abstract) {
            if (prop.Abstract.hasOwnProperty(name)) {
                //                console.log();
                //抽象方法前面加"Abstract_"前缀
                A.prototype["Abstract_" + name] = prop.Abstract[name];

                temp[name] = prop.Abstract[name];   //用于检查是否包含父类的抽象方法/属性 或 接口方法/属性
            }
        }

        //        //检查抽象类的公有方法+虚方法+抽象方法是否包含父类的抽象方法/属性 或 接口方法/属性
        //检查抽象类的公有方法+虚方法+抽象方法是否包含父类的接口方法/属性
        check(null, interface, temp);

        //静态属性/方法赋值
        for (k in Static) {
            A[k] = Static[k];
        }

        ////备份原型
        //A.prototype.backUp_prototype = extendDeep(A.prototype);

        return A;
    }



    //    //是否调用父类函数
    //    var base_flag = false;

    //创建普通类
    //父类_parent可以为{Class: xx, Interface: xx},或者直接为xx类
    function MyClass(_parent, _prop) {
        //        console.log("length = " + arguments.length);
        var Static = null;
        //                    Private = null,
        //            Public = null,
        //            Origin = null;

        var k = null, name = null;

        var parentClass = null, interface = null, prop = null, temp = {};
        //        var temp = null;

        //        //原型备份容器,用于创建实例时,恢复最初的原型(每次创建实例时,原型都保持不变)。
        //        var backUp_prototype = {};

        //原型恢复标志,用于防止第一次创建实例时恢复原型
        var mark_resume = false;


        //取出父类、接口
        if (arguments.length === 1) {
            prop = arguments[0];
            parentClass = null;
            interface = null;
        }
            //{Class: xx, Interface: xx}
        else if (typeof _parent === "object") {
            //            if (parent.Class)
            if (!_parent.Class && !_parent.Interface) {
                throw new Error("Please add Class or Interface!");
            }

            parentClass = _parent.Class;
            interface = _parent.Interface;

            prop = _prop;
        }
            //直接为xx类
        else if (typeof _parent === "function") {
            parentClass = _parent;
            interface = null;
            //            parent = _parent;
            //            interface = null;

            prop = _prop;
        }
        else {
            throw new Error("arguments is not allowed!");
        }



        //取出静态属性/方法、私有属性/方法、公有属性/方法
        //        Private = prop.Private;

        //        Public = prop.Public;

        Static = prop.Static ? prop.Static : null;



        //        //保存原始的私有属性,用于创建实例时,重置私有属性
        //        //        var Origin = {};
        //        //        Origin = Private
        //        Origin = operate.extendDeep(Private);
        //        YYC.Tool.extend.extend(Origin, Private);


        //        //访问公共属性/方法的入口,
        //        MyClass.Public = Public;


        // 本次调用所创建的类(构造函数)
        function F() {
            //            console.log(mark_resume);



            //防止第一次创建实例时恢复原型
            if (mark_resume) {
                //var t = F.prototype.backUp_prototype;
                //var m = F.prototype;

                //还原原型
                //extendDeep(F.prototype.backUp_prototype, F.prototype);
                extendDeep(F.backUp_prototype, F.prototype);


                //F.prototype.backUp_prototype = extendDeep(F.prototype);
            }
            else {
                mark_resume = true;
            }

            // 如果当前处于实例化类的阶段,则调用Init原型函数
            if (!initializing) {
                //                console.log("F");
                //                // 如果父类存在,则实例对象的baseClass指向父类的原型
                //                // 这就提供了在实例对象中调用父类方法的途径
                //                if (parentClass) {
                //                    this.baseClass = parentClass.prototype;
                //                    //                    console.log(this.baseClass);
                //                }
                this.Init && this.Init.apply(this, arguments);
            }

            //            this.Public = Public;

            //            console.log("F");


            //            if (this.)
            //            console.log(this._m);
            //            delete this._m;

            //            delete F.prototype._m;
            //            delete F.prototype._a;
            //            this._m = null;
            //            this._a = null;
            //            delete F.prototype._a;



            /*不能删除私有成员和保护成员!否则类的成员就不能调用到私有和保护的成员了(因为已经删除了)!
            对象的创建算法参考http://www.cnblogs.com/TomXu/archive/2012/02/06/2330609.html




            //删除私有成员和保护成员,这样外界就不能访问私有和保护成员了!
            for (name in this) {
            if (name.search(/(^_)|(^P_)/) !== -1) {
            delete F.prototype[name];
            //                                                    this[name] = null;
            }
              
            }
            */



            //            console.log(count);
            //            count++;

            //不使用MyClass.self!因为该属性为静态属性,如果创建了该类后,又创建了类A,则MyClass.self会指向类A!

            //            MyClass的静态属性self指向创建的类的实例,可以通过self来访问实例的属性和方法
            //            MyClass.self = this;





            //            Private.C();

            //            for (name in Private) {
            //                Private[name].call(this);
            //            }




        }




        //        Private.C = Private.C.call(null, Public);

        //        Private.call(F, null);

        //                Private.M = (function (pub) {
        //                    return function () {
        //                        Private.M.call(null, arguments);
        //                    }
        //                }(Public));


        //        for (name in Private) {
        //            Private[name] = function () {
        //                //            console.log("1111111");
        //                return function () {
        //                    //                console.log("222222222");
        //                    return Private[name].call(this, arguments);
        //                }

        //            };
        //        }



        //        Private.C = function () {
        //            return function () {
        //                Private.C.call(F, arguments);
        //            }
        //        };


        // 如果此类需要从其它类扩展
        if (parentClass) {

            initializing = true;
            //F.prototype = new parentClass();
            F.prototype = extendDeep(parentClass.prototype);


            F.prototype.constructor = F;

            //            for (name in parentClass.prototype) {
            //                if (parentClass.prototype.hasOwnProperty(name)) {
            //                    //私有成员不继承
            //                    if (!name.match(/^_/)) {
            //                        F.prototype[name] = parentClass.prototype[name];
            //                    }
            //                }
            //            }

            //            //删除父类的私有成员,保留本类的私有成员
            //            for (name in parentClass.prototype) {
            //                if (parentClass.prototype.hasOwnProperty(name)) {
            //                    //私有成员以“_”开头,可能有多个“_”(多层继承)
            //                    if (!name.match(/^_+/)) {
            //                        //                                                delete parentClass.prototype[name];
            //                        F.prototype[name] = parentClass.prototype[name];
            //                    }
            //                }
            //            }

            //            console.log(F.prototype.constructor);


            // 如果父类存在,则实例对象的baseClass指向父类的原型。
            // 这就提供了在实例对象中调用父类方法的途径。
            //baseClass的方法是指向parentClass的,不是指向F(子类)的!
            //F.prototype.baseClass = parentClass.prototype;


            F.prototype[getNoRepeatStrInPrototype(parentClass.prototype, "baseClass")] = parentClass.prototype;

            initializing = false;
        }

        if (prop.Init) {



            // 如果此类继承自父类parent并且父类原型中存在同名函数name
            if (parentClass &&
    typeof prop.Init === "function" &&
    typeof F.prototype.Init === "function") {
                F.prototype.Init = function (name) {
                    return function () {
                        this.base = function () {
                            return parentClass.prototype[name].apply(parentClass.prototype, arguments);
                        };
                        //指向子类,可以用于模版模式
                        this.baseToSubClass = parentClass.prototype[name];
                        //执行fn并返回执行的结果
                        //此处的arguments为F.prototype[name]方法传入的形参。
                        return prop[name].apply(this, arguments);
                    };

                }("Init");
            }
            else {
                F.prototype.Init = prop.Init;
            }
        }


        //        Private.call(this);

        //        if (parentClass && parentClass.prototype["JudgeDoubleHit"]) {
        //            console.log(parentClass.toString());


        if (parentClass) {
            for (name in parentClass.prototype) {
                if (parentClass.prototype.hasOwnProperty(name)) {
                    //如果不是抽象方法/保护方法/私有方法/接口成员,则加入到temp中。
                    //用于添加父类的密封方法(因为子类并没有加入父类的密封方法)。
                    if (!name.match(/^Abstract_/) || !name.match(/^P_/) || !name.match(/^_/) || !name.match(/^Interface_/)) {
                        temp[name] = parentClass.prototype[name];
                    }
                }
            }
        }





        //        }

        //        if (this.baseClass.Protected) {
        //            if (this.baseClass.Protected.Sealed) {

        //                for (k in this.baseClass.Protected.Sealed) {
        //                    temp[k] = this.baseClass.Protected.Sealed[k];
        //                }
        //            }
        //        }


        if (prop.Private) {
            //私有属性/方法直接覆盖
            for (name in prop.Private) {
                if (prop.Private.hasOwnProperty(name)) {
                    F.prototype[name] = prop.Private[name];
                }
            }
        }

        //        if (!prop.Public) {
        //            throw new Error("Class must have public methods!");
        //        }
        //        else {

        //        }


        //保护成员
        if (prop.Protected) {
            for (name in prop.Protected) {
                if (prop.Protected.hasOwnProperty(name)) {
                    //检查虚方法,虚方法放到Public或Protected中
                    if (name === "Virtual") {
                        addVirtual(prop["Protected"][name], F, temp);
                        continue;
                    }
                    //密封的方法(不允许子类重写)
                    if (name === "Sealed") {
                        addSealed(prop["Protected"][name], F, temp);
                        continue;
                    }

                    F.prototype[name] = prop.Protected[name];

                    //如果父类有保护抽象成员,此处检查子类的保护成员是否实现了父类的保护抽象成员
                    temp[name] = prop.Protected[name];
                }
            }
        }

        //        //虚方法(不能为虚属性)
        //        if (prop.Virtual) {
        //            for (name in prop.Virtual) {
        //                if (prop.Virtual.hasOwnProperty(name)) {
        //                    if (typeof prop.Virtual[name] !== "function") {
        //                        throw new Error("Virtual attribute is not allowed!");
        //                    }
        //                    else {
        //                        F.prototype[name] = prop.Virtual[name];

        //                        temp[name] = prop.Virtual[name];    //加入temp
        //                    }
        //                }
        //            }
        //        }

        if (prop.Abstract) {
            throw new Error("Only abstractClass can have abstract methods!");
        }



        if (prop.Public) {
            // 覆盖父类的同名公有方法
            for (name in prop.Public) {
                //            console.log("for in name = " + name);
                //            //私有属性/方法不加入到原型中
                //            if (name === "Private") {
                ////                console.log("continue");
                //                continue;
                //            }

                if (prop.Public.hasOwnProperty(name)) {
                    //检查虚方法,虚方法放到Public或Protected中
                    if (name === "Virtual") {
                        addVirtual(prop["Public"][name], F, temp);
                        continue;
                    }
                    //密封的方法(不允许子类重写)
                    if (name === "Sealed") {
                        addSealed(prop["Public"][name], F, temp);
                        continue;
                    }
                    //                    console.log("Public");
                    //                    console.log("name = " + name);
                    //                    console.log("prop.Public[name] = " + prop.Public[name]);
                    temp[name] = prop.Public[name];     //加入temp

                    // 如果此类继承自父类parent并且父类原型中存在同名函数name
                    if (parentClass &&
            typeof prop.Public[name] === "function" &&
            typeof F.prototype[name] === "function") {
                        //                        console.log("parent!");




                        F.prototype[name] = function (name) {
                            return function () {
                                /*此处如果写成“this.base = parentClass.prototype[name];”,则在使用this.base()调用父类同名方法时,
                                父类同名方法的this指针是指向F的!(即指向子类,而不是指向父类!)   为什么????
                                如:
                                var Person = MyAbstract({
                                Init: function (name) {
                                this.name = name;
                                },
                                Public: {
                                m: 1,
                                getEmployeeID: function () {
                                console.log(this.m);
                                }
                                }
                                }
                                });


                                var Employee = MyClass({
                                Init: function (name) {
                                this.name = name;
                                },
                                Public: {
                                m: 100,
                                getEmployeeID: function () {
                                this.baseClass.getEmployeeID();
                                this.base();
                                }
                                }
                                });

                                var m = new Employee();
                                m.getEmployeeID();    //输出:1  100

                                分析:
                            
                                this.baseClass.getEmployeeID()的this指向Person,而this.base()的this指向Employee!

                                解决方案:

                                用apply修正this.base()中的this,使其指向父类。
                                */


                                //                                if (!this.base) {
                                //此处不用创建闭包了!因为外面已经创建了闭包,name已经被保存了!
                                this.base = function () {
                                    //这个写法也可以!为什么不用apply修正this也行??!
                                    //parentClass.prototype[name](); 

                                    //此处的arguments为base方法传入的形参
                                    //注意!要加上“return”,这样才能返回parentClass.prototype[name]的返回值
                                    return parentClass.prototype[name].apply(parentClass.prototype, arguments);

                                    //                                    this.baseClass.
                                };
                                //                                }
                                //                                if (!this.baseToSubClass) {
                                //指向子类,可以用于模版模式
                                this.baseToSubClass = parentClass.prototype[name];
                                //                                }

                                //                                this.base = function () {
                                //                                    //                                    console.log(base_flag);

                                //                                    Private = {
                                //                                    };
                                ////                                    base_flag = true;
                                //                                    return parent.prototype[name];
                                //                                };
                                //                            console.log("arg = " + arg);

                                //执行fn并返回执行的结果
                                //此处的arguments为F.prototype[name]方法传入的形参。
                                return prop.Public[name].apply(this, arguments);
                            };

                        }(name);

                    }
                    else {
                        //                    console.log();
                        //公有属性
                        if (typeof (prop.Public[name]) !== "function") {
                            F.prototype[name] = prop.Public[name];
                        }
                            //公有方法
                        else {
                            /* 如果不传入Public[name],而直接在自执行函数中调用Public[name],如
                            F.prototype[name] = function () {
                            return function () {
                            prop.Public[name].apply(this, arguments);
                            };
                            } ();

                            或者写成:
                            F.prototype[name] = function () {
                            prop.Public[name].call(this, arguments);
                            };
                        
                        
                            这样的话,在创建实例时调用方法时,都会执行MyClass中的最后一个函数!见下例
                        
                            var Person = MyClass({
                            Init: function (name) {
                            this.name = name;
                            },
                            getName: function () {
                            console.log("getName");
                            },
                            getEmployeeID: function ($private) {
                            console.log("Person getEmployeeID");
                            }
                            });
                            var m = new Person("name");     
                            m.getName();    //第一种和第二种写法此处会输出:"Person getEmployeeID"
                

                            这样执行的原因是:

                            (引用自“深入理解JavaScript系列(16):闭包(Closures)”)
                            同一个父上下文中创建的闭包是共用一个[[Scope]]属性的。也就是说,
                            某个闭包对其中[[Scope]]的变量做修改会影响到其他闭包对其变量的读取。
                            这就是说:所有的内部函数都共享同一个父作用域。

                            也就是说,function里面的name都是共用父作用域中的name!所以此处F.prototype[name]被激活的时候,
                            name都为最后一个值即"getEmployeeID"。
                            所以F原型上的方法都指向"getEmployeeID"

                            解决方案:

                            创建一个闭包来保存name的值。
                            */
                            F.prototype[name] = function (name) {
                                return function () {
                                    return prop.Public[name].apply(this, arguments);     //执行fn并返回执行的结果
                                };
                            }(name);

                        }
                    }
                }
            }
        }




        //检查公有成员和虚函数是否实现了抽象方法/属性 或 接口方法/属性
        check(parentClass, interface, temp);


        //静态属性/方法赋值
        for (k in Static) {
            F[k] = Static[k];
        }



        //备份原型
        //F.prototype.backUp_prototype = extendDeep(F.prototype);
        F.backUp_prototype = extendDeep(F.prototype);


        return F;
    };

    YYC.Pattern.namespace("Frame").MyInterface = MyInterface;

    YYC.Pattern.namespace("Frame").MyAbstract = MyAbstract;

    YYC.Pattern.namespace("Frame").MyClass = MyClass;
}());
View Code

相关文章: