2017-04-26 80 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