调用子类函数时调用的超类函数

superclass function being called when subclass function is invoked

本文关键字:调用 类函数 超类      更新时间:2023-09-26

我真的很努力想出一个标题,但基本上我正在 html5 画布中开发一款游戏,并在与 ai 对战时有一个叫做 player 的类,带有一个子类 aiPlayer。更新播放器的代码如下所示:

  var entitiesCount = this.entities.length;
  for (var i = 0; i < entitiesCount; i++) {
      var entity = this.entities[i];
      entity.update();
      if (entity instanceof special && entity.x > WIDTH || entity.x + 200 < 0) {
          this.entities.splice(i, 1);
          entitiesCount--;
      }
  }

但是,aiPlayer永远不会使用aiPlayer更新功能进行更新。我已经打印出了每个实体的构造函数,有一个播放器和一个 aiPlayer。但是,在打印出他们正在调用的方法时,他们都在调用播放器更新。有谁知道它为什么要这样做?此外,如果有帮助,aiPlayer 更新如下所示:

aiPlayer.prototype.update = function() {
    if((this.game.timer.gameTime % this.moveTime) > (this.moveTime * 0.9)) {        
        this.chooseMove();
    }
    Player.prototype.update.call(this);
};

AI 构造函数如下所示:

function aiPlayer (game, character, x, y, health) {
    Player.call(this, game, character, x, y, health, PLAYER2_CONTROLS, "left");
    aiPlayer.prototype = new Player(this.game, this.character, this.x, this.y,
                                this.health, this.control, this.facing);
    aiPlayer.prototype.constructor = aiPlayer;
    this.controls = PLAYER2_CONTROLS;
    this.attackLength = 50;
    this.fleeLength = 70;
    this.moveTime = 1;
    this.prevControl = "idle";
}
function aiPlayer (game, character, x, y, health) {
    Player.call(this, game, character, x, y, health, PLAYER2_CONTROLS, "left");
    aiPlayer.prototype = new Player(this.game, this.character, this.x, this.y,this.health, this.control, this.facing);
    aiPlayer.prototype.constructor = aiPlayer;
    this.controls = PLAYER2_CONTROLS;
    this.attackLength = 50;
    this.fleeLength = 70;
    this.moveTime = 1;
    this.prevControl = "idle";
}

这些行在这里

aiPlayer.prototype = new Player(this.game, this.character, 
                                this.x, this.y,this.health, 
                                this.control, this.facing);
aiPlayer.prototype.constructor = aiPlayer;

错了。他们错了,因为

  • 您正在将原型设置为Player的实例
  • 每次创建 aiPlayer 的新实例时,您都会重置 aiPlayer 原型的原型和构造函数。您应该将所有修改移动到构造函数之外的原型,如下所示:

-

function aiPlayer (game, character, x, y, health) {
    Player.call(this, game, character, x, y, health, PLAYER2_CONTROLS, "left");
    this.controls = PLAYER2_CONTROLS;
    this.attackLength = 50;
    this.fleeLength = 70;
    this.moveTime = 1;
    this.prevControl = "idle";
}
aiPlayer.prototype.someMethod = function someMethod() { 
    ....
}

设置子类原型的正确方法是这样的

aiPlayer.prototype = Object.create(Player.prototype, {
    constructor : {
        value : aiPlayer
    }
};

这将aiPlayer原型设置一个新对象,该对象继承自Player.prototype(即将Player.prototype作为其原型),并aiPlayer注册为其构造函数

此外,Player.update是从aiPlayer调用的,因为您在此处显式调用它

aiPlayer.prototype.update = function() {
    if((this.game.timer.gameTime % this.moveTime) > (this.moveTime * 0.9)) {        
        this.chooseMove();
    }
    Player.prototype.update.call(this); //you call the Player.update()
}; 

考虑到上述情况,您应该如何注册aiPlayer.update

aiPlayer.prototype = Object.create(Player.prototype, {
    constructor : {
        value : aiPlayer
    }
};
aiPlayer.prototype.update = function update() {
//your code here
}

现在,当您创建新的aiPlayer对象实例时,继承链将如下所示

aiPlayerInstance --> aiPlayer.prototype --> Player.prototype

当你调用aiPlayerInstance.update()时,它将首先查看aiPlayer.prototype,并且由于aiPlayer.prototype确实有一个名为update的方法,它将执行它,并且它不会在继承链中查看任何更远的位置(即在Player.prototype