【问题标题】:superclass function being called when subclass function is invoked调用子类函数时调用超类函数
【发布时间】:2015-03-15 01:45:44
【问题描述】:

我真的很难想出一个标题,但基本上我正在开发一个 html5 画布中的游戏,并且有一个名为 player 的类,它有一个子类 aiPlayer,用于对抗 ai。更新播放器的代码如下所示:

  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 更新功能进行更新。我已经打印出每个实体的构造函数,并且有一个 Player 和一个 aiPlayer。但是,当打印出他们正在调用的方法时,他们都在调用 Player 更新。有谁知道它为什么会这样做? 此外,如果有帮助,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";
}

【问题讨论】:

    标签: javascript html inheritance canvas


    【解决方案1】:
    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
        }
    };
    

    这会将一个继承自Player.prototype 的新对象设置为aiPlayer 原型(即,将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)

    【讨论】:

      猜你喜欢
      • 2016-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-02
      • 2013-06-24
      • 1970-01-01
      • 2011-02-16
      相关资源
      最近更新 更多