2017-04-26 83 views
0

唷,即使这个问题很难写。这里的问题:我有一个“游戏”,更像是一个随机的模拟器,它需要选择从操作数组随机行动,像这样的:执行从Javascript中的构造函数数组中访问构造函数的父节点的“静态”方法

actions = [ Action1, Action2, Action3 ] 

我已经行动写成类从继承操作父类:

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为它。

+0

'Action1.prototype =新的Action();'是的原因[您的OOP不起作用]一个(https://stackoverflow.com/questions/12592913/what-is-the-原因是使用新关键字在这里) – Bergi

回答

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; 
    } 
} 
+0

谢谢,这个作品。我仍然不知道为什么静态方法在完成旧方法时没有被继承,但是这更简单,更优雅,我不在乎。 – Deuxis

+1

@Deuxis因为在ES5中,子类只做实例的继承,而不是构造函数(包含静态属性)。 – Bergi

0

它看起来对我像你调用一个实例checkRequirements()

a.checkRequirements(); 

但它是静态实现:

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

你可能想给这个函数的原型进行绑定,这样的变化上面的代码为:

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

然后当你wan T以派生类型重写此,像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

+0

这是行不通的,并且没有实例afaik,我从来不会调用'new'(并且我甚至没有看到**在数组中如何**情况)。我从一个类的数组中选择一个,然后调用它的静态方法。如果我在子Action1中实现静态'checkRequirements',它就会起作用 - 它不会从父Action中继承。这是使我在每个子操作中实现'init()'的同样问题,即使它应该从父类继承。哦,我想我只是复制并粘贴'checkRequirements()'。离开这个问题,也许有人会解释。 – Deuxis

+0

@Deuxis你正在从'init()'函数中调用new:'var a = new Action1();'。让我更新答案......毫无疑问,这将是一个优雅的解决方案。 – series0ne

+0

@Deuxis出于好奇,你有没有考虑过先用TypeScript写这个,看看编译器产生了什么? – series0ne