2017-04-26 1 views
0

Phewのコンストラクタ配列からアクセスされたコンストラクタの親の "静的"メソッドを実行します。ここで問題です:私は、「ゲーム」を持っている以上、このように、アクションの配列からランダムなアクションを選択する必要がランダムシミュレータのように: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で動作する必要があります。それのためのクロム。

+0

'Action1.prototype =新しいアクション();' [あなたのOOPが動作しない]理由の一つです(https://stackoverflow.com/questions/12592913/what-is-the-ここで新しいキーワードを使用する理由) – Bergi

答えて

1

あなたはChromeで作業する必要があるだけなので、すべての継承を適切に行う構文であるES6 classを使用することをお勧めします。これには、Actionコンストラクタからプロパティ( "静的クラスメンバ")を継承するコンストラクタがAction1に含まれています。

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サブクラス化はインスタンスの継承のみを行い、コンストラクタ(静的プロパティを保持する)では継承しませんでした。 – Bergi

0

それはあなたがインスタンス上checkRequirements()を呼んでいるように私には見えます:

a.checkRequirements(); 

しかし、それは静的に実装されています:あなたはおそらくプロトタイプにこの機能をバインドしたい

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

を、その変更上記のコードは

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

です派生型でこれをオーバーライドするtは、Action1のように、あなたがこれを行うことができます。コメントを1として

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'を呼び出すことはありません。状況)。私はクラスの配列から1つを選択し、その静的メソッドを呼び出しています。これは、子Action1に静的な 'checkRequirements'を実装すると機能します。親Actionから継承されません。これは、親から継承する必要があるにもかかわらず、すべての子アクションで 'init()'を実装するのと同じ問題です。まあ、私はちょうど 'checkRequirements()'もコピーアンドペーストするでしょう。しかし、質問を残して、誰かが説明するかもしれない。 – Deuxis

+0

@Deuxis 'init()'関数からnewを呼び出しています: 'var a = new Action1();'。私は答えを更新しましょう...間違いなくエレガントな解決策になります。 – series0ne

+0

@Deuxisは好奇心を忘れていますが、これをまずTypeScriptで書いてみて、コンパイラが何を生成しているのか見てきましたか? – series0ne