简体   繁体   English

修改子类实例中的变量

[英]Modifying variables in subclass instances

I've become hopelessly addicted to Screeps recently, and I refactored some code to make a task-based implementation. 我最近对Screeps已经无可救药地沉迷,我重构了一些代码来实现基于任务的实现。 Tasks are things like "walk to and then harvest until you are at full capacity" and are based off of a single base task template written as an ES6-style class. 任务是“走到然后收获直到满负荷”之类的事情,并且基于作为ES6风格的类编写的单个基本任务模板。 Creeps can be assigned tasks through a wrapper (tasks.js) that loads the relevant task file and returns a new task instance. 可以通过加载相关任务文件并返回新任务实例的包装器(tasks.js)为Creeps分配任务。

Today I ran into a strange bug that makes me think I don't fully understand Javascript's inheritance model. 今天我遇到了一个奇怪的错误,让我觉得我不完全理解Javascript的继承模型。 Below is the relevant code: 以下是相关代码:

Task.js: (base task class) 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: (harvesting 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: (wrapper to generate a new task instance via a function call) 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: (behavior model for a harvester creep) 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();
    },
   ...
}

When I assign a creep to harvest from a source, I create a new task from task_harvest.js, set its quiet property to be true , and bind it and its target to the creep. 当我从一个源中分配一个creep来收获时,我从task_harvest.js创建一个新任务,将其quiet属性设置为true ,并将它和它的目标绑定到creep。 Once the creep has a task it is instructed to run it until it becomes invalid (code not included above). 一旦creep有任务,它就会被指示运行它直到它变得无效(代码不包含在上面)。 The creep executes the task fine, but it still logs everything to the console. creep执行任务很好,但它仍然将所有内容记录到控制台。

I would think that in harvester.js, when I set taskHarvest.quiet = true; 我认为在harvester.js中,当我设置taskHarvest.quiet = true; , the behavior imported from Task.js would see this.quiet as true . ,从Task.js导入的行为会将this.quiet视为true However, it seems as though that is not the case. 然而,似乎并非如此。 In roleHarvester , running console.log(creep.task.quiet) returns true , but in Task , running console.log(this.quiet) when the creep is executing the assigned task gives false . roleHarvester ,运行console.log(creep.task.quiet)返回true ,但在Task ,当creep执行时运行console.log(this.quiet) ,赋值为false

I could add quiet into the constructor as an optional parameter, but that's convoluted and I want to know why what I'm doing isn't working. 我可以将quiet添加到构造函数中作为可选参数,但这是令人费解的,我想知道为什么我正在做的事情不起作用。

Nevermind, it actually wasn't an inheritance problem; 没关系,它实际上不是遗传问题; it was a problem caused by the game mechanics: taskHarvest.quiet wasn't getting deleted each tick. 这是一个由游戏机制引起的问题: taskHarvest.quiet没有被删除每个tick。 Screeps only allows you to store JSON-serializable objects in memory, so I store the task settings in memory and reconstruct the task object each tick: Screeps只允许您将JSON可序列化对象存储在内存中,因此我将任务设置存储在内存中并重新构建每个tick的任务对象:

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 wasn't getting stored in memory, so it wouldn't persist past the first tick of the task. taskHarvest.quiet没有存储在内存中,所以它不会持续超过任务的第一个滴答。 I now store all instance-level adjustable parameters in a task.data object, so task.quiet is now task.data.quiet . 我现在将所有实例级可调参数存储在task.data对象中,因此task.quiet现在是task.data.quiet This fixed the problem; 这解决了这个问题; sorry for producing any confusion! 对不起产生任何困惑!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM