2017-02-21 17 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, установите его свойство quiet быть true, и связать его и его цель ползучести. После того, как у ползунки есть задача, ей будет предложено запустить ее, пока она не станет недействительной (код не включен выше). Ползучесть отлично выполняет задачу, но она все еще записывает все на консоль.

Я думал бы, что в harvester.js, когда я установил taskHarvest.quiet = true;, поведение, импортированное из Task.js, увидело бы this.quiet как true. Однако кажется, что это не так. В roleHarvester, работает console.log(creep.task.quiet) возвращает true, но в Task, работает console.log(this.quiet), когда ползучесть выполняет назначенное задание, дает false.

Я могу добавить quiet в конструктор как необязательный параметр, но это запутанно, и я хочу знать, почему то, что я делаю, не работает.

+1

Когда вы проверяете значение 'this.quiet', вы на 100% уверены, что' this' верен? Я не вижу ничего явно неправильного или неверного понимания вашего наследства. Установка 'taskHarvest.quiet = true;' должна работать нормально. – jfriend00

+0

@ jfriend00 в Task.js, 'this' должен ссылаться на' Task', а в task_harvest.js 'this' должен ссылаться на' taskHarvest', который не определяет 'this.quiet', поэтому он должен ссылаться на унаследованная переменная Task.js. Затем, когда я создаю экземпляр 'taskHarvest' и устанавливаю его' instance.quiet = true', он, похоже, не меняет унаследованное значение из 'Task'. Если я делаю 'console.log (экземпляр.quiet) ', он возвращает' true', но если я добрался до 'Task' и сделаю' console.log (this.quiet) ', он вернет' false'. –

+0

Я не спрашивал вас, что это должно быть. Я спросил, что это на самом деле. Здесь есть только две возможности. Что-то еще устанавливает '.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.quiet теперь task.data.quiet. Это поставило проблему; извините за создание путаницы!