1

下面是一个如何使用 Extends mutator 的简单示例:

var firstClass = new Class({
    aMethod: function(){
        console.log('firstClass method');
    }
});


var secondClass = new Class({
    Extends:firstClass,
    aMethod: function(){
        this.parent();
        console.log('secondClass method');
    },
    initialize: function(){
        this.aMethod();
    }
});

var instance = new secondClass();

//Output:
//      firstClass method
//      secondClass method

我想实现相同的行为,但使用这样的类构造函数:

var firstClass = new Class({
    methods: {
        aMethod: function(){
            console.log('firstClass method');
        }
    }
});


var secondClass = new Class({
    Extends:firstClass,
    methods: {
        aMethod: function(){
            this.parent();
            console.log('secondClass method');
        }
    },

    initialize: function(){
        this.methods.aMethod.call(this);
    }
});

var instance = new secondClass();

//Output:
//      Error: The method "initialize" has no parent.

instance.methods.aMethod.call(this);

//Output:
//      TypeError: this.parent is not a function

不幸的是,我的 Mootools Fu 不是很强大,所以我有点不知所措。这可能与 Extends 当前的工作方式有关吗?如果不是,那么我想努力实现一个解决方案来做到这一点,但是我需要一些指导来让我朝着正确的方向开始(制作一个自定义的 Mutator?修改核心源?还有别的吗?)。任何关于如何进行的建议或想法将不胜感激。

更新

我想出了一种使用基于模式的突变器(Github)来做到这一点的方法。需要包含 Mark 的代码才能使以下工作:

(function(){

    /* Utility functions */

    Object.extend({
        containsMethods:function(obj){
            if(typeOf(obj) != 'object') return false;
            return Object.getLength(Object.filter(obj, function(item){return typeOf(item) == 'function';})) > 0;
        },

        containsObjects:function(obj){
            if(typeOf(obj) != 'object') return false;
            return Object.getLength(Object.filter(obj, function(item){return typeOf(item) == 'object';})) > 0;
        }
    });

    var getInheritance = function(obj, key){
        var temp = {};
        if(obj){
            if(obj.inheritance !== undefined){
                temp[key] = obj.inheritance;
            }
            delete obj.inheritance;
        }
        return temp;
    }

    /* Recursive function to turn specially keyed object literals in the constructor into class instances with inheritance */

    var classify = function(obj, inherit, key, imap){
        if(typeOf(obj) != 'object'){return obj;}

        if(key == undefined){
            key = '';
        }

        var inheritance = 'extends';

        if(imap != null){
            imap = Object.append(imap, getInheritance(obj, key));
            imap = Object.append(imap, getInheritance(inherit, key));

            if(imap[key] != undefined){
                inheritance = imap[key];
            }
        }

        var i = 'extends';

        for(var k in inherit){
            if(!inherit.hasOwnProperty(k)) {continue;}

            i = 'extends';

            if(imap != null){

                if(typeOf(inherit[k]) == 'object'){
                    imap = Object.append(imap, getInheritance(inherit[k], k));
                }

                if(typeOf(obj[k]) == 'object'){
                    imap = Object.append(imap, getInheritance(obj[k], k));
                }                   

                if(imap[k] != undefined){
                    i = imap[k];
                }
            }

            /* Needed to clean up properties when inheritance == false */
            if(inherit[k] === undefined){
                delete inherit[k];
            }

            if(typeOf(inherit[k]) == 'object' && i === false && !Object.keys(obj).contains(k)){
                obj[k] = undefined;
                continue;
            }

            if(obj[k] && typeOf(obj[k]) == 'object' && i !== false){
                obj[k] = classify(obj[k], inherit[k], k, imap);
            }
        }

        if(Object.containsMethods(obj)){
            var constructor = {};

            if(inherit != undefined && inheritance !== false){

                if(inheritance == 'implements'){
                    constructor.Implements = (inherit.$constructor ? inherit.$constructor : new Class(inherit));
                }else {
                    constructor.Extends = (inherit.$constructor ? inherit.$constructor : new Class(inherit));
                }
            }

            obj = new (new Class(Object.append(constructor, obj)));

        }else {

            if(!Object.containsMethods(inherit)){
                obj = Object.append({}, inherit, obj);
            }
        }

        return obj;
    };

    /* Mutator */

    Class.defineMutator(/^_(\w+)_/, function(params, key){
        var old_key = key;
        var key = key.replace(/_/g, "");
        var c = null;
        var imap = null;

        if(this.$constructor){
            imap = this.$constructor.imap = (this.$constructor.imap || {});
        }

        if(this.prototype[key] != undefined){
            c = classify.call(this, params, this.prototype[key], '', imap);
        }else {
            c = classify.call(this, params, undefined, '', imap);
        }

        this.prototype[key] = c;
        delete this[old_key];
    });

})();

mutator 模式只是一个用单个下划线包围的键名(例如:_方法_)。类构造函数中的嵌套对象可以包含属性和方法或其他嵌套对象的任意组合。每个单独的对象都可以有一个带有键“继承”的属性,该属性采用以下值:“实现”、“扩展”或 false。Implements 和 extends 对应于 Implements 和 Extends Mootools 类修改器的行为。Extends 是默认值,并且是在没有为继承属性提供任何内容时使用的方法。false 值将阻止给定对象(以及嵌套在其中的任何对象)完全被继承。

包括示例在内的整个代码可以在这里找到

4

0 回答 0