执行"静态"从Javascript中的构造函数数组访问的构造函数的父项的方法

时间:2017-04-26 06:26:56

标签: javascript oop inheritance

p,即使这个问题很难写。问题在于:我有一个游戏",更像是一个随机模拟器,它需要从一系列动作中选择一个随机动作,如下所示:

actions = [ Action1, Action2, Action3 ]

我将操作编写为继承自Action父类的类:

function Action() {
    this.targets = [];
    this.used = [];
    this.execute = function(player) {
        doStuff();
        return whatever;
    };
}
//btw the below I've seen in a JS OOP tutorial but it doesn't work and I have to implement init() in every child action
Action.init = function(player) {
    var a = new this.constructor();
    return a.execute(player);
};
Action.checkRequirements = function() {
    return true;
};

Action1.prototype = new Action();
Action1.prototype.constructor = Action1;
function Action1 {
    this.execute = function(player) {
        doStuff();
        return whatever;
    }
}
Action1.init = function(player) {
    var a = new Action1();
    return a.execute(player);
}

所以我执行一个动作并获得结果的是var foo = actions.getRandomVal().init();(getRandomVal是一个简单的自定义脚本,它从数组中返回一个随机值)它工作正常,创建了一个对象实例正确地继承所有属性和方法,执行exec()方法并返回其结果......但现在我有一个checkRequirements()方法,我希望在我希望做的100多个动作中实现10%,我希望它只是从Action类继承而来,当它没有在子类中实现时,它只返回true,我不知道如何。如果我执行var a = actions.getRandomVal();然后a.checkRequirements();它会抛出一个异常,即a.checkRequirements不是函数。

PS:对于(大)朋友群来说,这是一个相对较小的非盈利项目,我不需要它在每个浏览器中工作,它需要在Chrome中工作,我可以告诉他们使用Chrome。

2 个答案:

答案 0 :(得分:1)

由于您只需要使用Chrome,我建议使用ES6 class语法,该语法可以正确地执行所有继承,而不会陷入困境。这包括您的Action1构造函数,以便按照您的预期从Action构造函数继承属性(“静态类成员”)。

class Action {
    constructor() {
        this.targets = [];
        this.used = [];
    }
    execute(player) {
        doStuff();
        return whatever;
    }
    static init(player) {
        var a = new this(); // no .constructor
        return a.execute(player);
    }
    static checkRequirements() {
        return true;
    }
}

class Action1 {
    execute(player) {
        doOtherStuff();
        return whateverelse;
    }
}

答案 1 :(得分:0)

我认为您在某个实例上调用了checkRequirements()

a.checkRequirements();

但它是静态实施的:

Action.checkRequirements = function() {
    return true;
};

您可能希望将此函数绑定到原型,因此请将上面的代码更改为:

Action.prototype.checkRequirements = function() {
    return true;
};

然后,如果要在派生类型中覆盖此项,例如Action1,则可以执行此操作:

Action1.prototype.checkRequirements = function () {
    return (whatever);
}

根据评论,我的猜测是你想要这样的......

// base Action type providing basic implementation
// Wrapped in an IIFE to prevent global scope pollution
// All functions are prototype bound to allow prototypical inheritance.
var Action = (function () {
    function Action() {
        this.targets = [];
        this.used = [];
    };

    Action.prototype.doStuff = function () {
        return;
    }

    Action.prototype.execute = function (player) {
        this.doStuff();
        return "whatever";
    }

    Action.prototype.checkRequirements = function () {
        return "foo";
    }

    return Action;
})();

var Action1 = (function () {
    Action1.prototype = new Action();
    Action1.prototype.constructor = Action1;

    function Action1() {
    }

    Action1.prototype.checkRequirements = function () {
        // Super call
        return Action.prototype.checkRequirements.call(this);
    }

    return Action1;
})();

var Action2 = (function () {
    Action2.prototype = new Action();
    Action2.prototype.constructor = Action2;

    function Action2() {
    }

    Action2.prototype.checkRequirements = function () {
        return "bar";
    }

    return Action2;
})();

// Set up array.
var array = [Action1, Action2];

// Create instances (this is where you would pick at random)
var a1 = new array[0]();
var a2 = new array[1]();
// var aofn = new array[rnd]();

// Tests
alert(a1.checkRequirements()); // Should "foo" because it called super (Action).
alert(a2.checkRequirements()); // Should "bar" because it's overridden.

<强> Check it out on TypeScript Playground