2017-02-21 9 views
1

私は最近、絶望的にScreepsに夢中になってしまい、タスクベースの実装を行うためにいくつかのコードをリファクタリングしました。タスクとは、「歩くまで歩いた後、フルキャパシティーになるまで収穫する」のようなもので、ES6スタイルのクラスとして書かれた単一の基本タスクテンプレートに基づいています。クリープには、関連タスクファイルをロードして新しいタスクインスタンスを返すラッパー(tasks.js)を使用してタスクを割り当てることができます。サブクラスインスタンスの変数を変更する

今日私はJavascriptの継承モデルを完全に理解していないと思う奇妙なバグが発生しました。以下関連するコードである:

Task.js:(ベース・タスク・クラス)

class Task { 
    constructor(taskName) { 
     // Parameters for the task 
     this.name = taskName; // name of task 
     this.quiet = false; // suppress console logging if true 
     this.creep = [creep assigned to this task] 
     this.target = [thing task operates on, e.g. "repair this wall"] 
     ... 
    } 
    ... 
    // Execute this task each tick. Returns nothing unless work is done. 
    step() { 
     ... 
     if (creep.pos.inRangeTo(target, this.targetRange)) { 
      var workResult = this.work(); 
      console.log(this.quiet) // < returns false, should be true? 
      if (workResult != OK && this.quiet == false) { 
       creep.log("Error: " + workResult); // < is printed when run 
      } 
      return workResult; 
     } [else move to target] 
    } 
    ... 
    // Task to perform when at the target 
    work() { 
     // overwrite this in child class 
    } 
} 

module.exports = Task; 

task_harvest.js:(収穫タスク)

var Task = require('Task'); 

class taskHarvest extends Task { 
    constructor() { 
     super('harvest'); 
     // no mention of this.quiet here 
    } 
    ... 
    work() { 
     console.log("harvest:" + this.quiet); 
     return this.creep.harvest(this.target); 
    } 
} 
module.exports = taskHarvest; 

tasks.js:生成する(ラッパー新しいタスクインスタンス関数呼び出しを経由して)

module.exports = function (taskName) { 
    var TaskClass = require('task_' + taskName); // all tasks follow this naming pattern 
    var taskInstance = new TaskClass; 
    return taskInstance; 
}; 

harvester.js:(収穫クリープのための行動モデル)

var tasks = require('tasks'); 
var roleHarvester = { 
    ... 
    harvest: function (creep) { 
     var target = Game.getObjectById(creep.memory.assignment); 
     var taskHarvest = tasks('harvest'); 
     taskHarvest.quiet = true; // < this task shouldn't print anything 
     creep.assign(taskHarvest, target); // assigns to creep.task 
     return OK; 
    }, 
    ... 
    run: function (creep) { // executed every tick 
     // execute the task 
     creep.task.step(); 
    }, 
    ... 
} 

私は元から採取するクリープを割り当てると、私はtask_harvest.jsから新しいタスクを作成し、trueこと、およびクリープに、その標的に結合するために、そのquietプロパティを設定します。クリープにタスクが設定されると、クリープが無効になるまで実行されるよう指示されます(コードは上記に含まれていません)。クリープはタスクをうまく実行しますが、それでもすべてをコンソールに記録します。

harvester.jsでtaskHarvest.quiet = true;と設定すると、Task.jsからインポートされた動作はthis.quietとしてtrueと表示されます。しかし、それはそうではないように思われる。 では、console.log(creep.task.quiet)を実行するとtrueが返されますが、には、​​が実行され、割り当てられたタスクを実行しているときにはfalseとなります。

オプションのパラメータとしてquietをコンストラクタに追加することはできますが、それは複雑で、私が何をしているのかが分かりません。

+1

'this.quiet'の値をチェックしているときに' this'が正しいことを100%確信していますか?明らかに間違ったことやあなたの相続について誤解されたことはありません。 'taskHarvest.quiet = true; 'を設定するとうまくいくはずです。 – jfriend00

+0

@ jfriend00はTask.jsで 'this'は' Task'を参照し、task_harvest.jsでは 'this'は' this.quiet'を定義していない 'taskHarvest'を参照する必要があります。 Task.js変数を継承します。それから 'taskHarvest'のインスタンスを作成し、' instance.quiet = true'を設定すると、継承された値を 'Task'から変更しているようには見えません。私が 'console.log(インスタンス。'true'を返しますが、' Task'に行って 'console.log(this.quiet)'を実行すると 'false'を返します。 –

+0

私はそれが "すべき"ことをあなたに尋ねなかった。私はそれが実際に何だったか尋ねました。ここには2つの可能性しかありません。何か他のものが '.quiet'を' false'に戻しているか、後で同じオブジェクトを見ていません。あなたはそれがどれであるか把握しなければなりません。あなたは、オブジェクトの生涯とそれに起こり得るすべてのことに私たちが従うために十分なコードを表示しません。例えば、私は 'creep.assign()'が何をしているのか分かりません。 – jfriend00

答えて

0

これは実際には継承の問題ではありませんでした。それはゲームのメカニックによって引き起こされた問題だった:taskHarvest.quietは、毎回削除されなかった。 Screepsはメモリ内でのみJSON-直列化可能オブジェクトを格納することができますので、私は、メモリ内のタスク設定を保存し、各ダニタスクオブジェクトを再構築:

Object.defineProperty(Creep.prototype, 'task', { 
    get: function() { // provide new task object recreated from literals stored in creep.memory.task 
     if (this.memory.task != null) { 
      var task = tasks(this.memory.task.name); 
      task.creepName = this.memory.task.creepName; 
      task.targetID = this.memory.task.targetID; 
      task.data = this.memory.task.data; // < task.quiet is now task.data.quiet 
      return task; 
     } else { 
      return null; 
     } 
    }, 
    set: function(newTask) { 
     if (newTask != null) { 
      this.log("use Creep.assign() to assign tasks. Creep.task = ___ should only be used to null a task."); 
     } else { 
      this.memory.task = newTask; 
     } 
    } 
}); 

taskHarvest.quietはメモリに保存されていませんでしたので、それはないだろうタスクの最初のティックを過ぎても持続する。すべてのインスタンスレベルの調整可能なパラメータをtask.dataオブジェクトに格納するようになりました。したがって、task.quiettask.data.quietになりました。これで問題は解決しました。混乱を招いて申し訳ありません!