You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为游戏对象使用抽象构造函数?请修复我的继承代码问题

问题分析与解决方案

你遇到的核心问题是子类构造函数没有调用父类的构造函数,导致xCoord和yCoord这些实例属性没有被初始化到PlayerShip和EnemyShip的实例中。虽然你通过Object.create(Ship.prototype)把子类的原型链连到了Ship的原型上,但这只继承了原型上的方法/属性,实例属性必须通过调用父类构造函数来赋值。

修正后的代码

var player, enemies = [], enemiesCntInit = 10;

// 父构造函数:Ship
function Ship(x, y) { 
  this.xCoord = x; 
  this.yCoord = y; 
};

// 子类PlayerShip:必须调用父构造函数初始化实例属性
function PlayerShip(x, y) { 
  // 调用Ship构造函数,将当前实例this传入,初始化xCoord和yCoord
  Ship.call(this, x, y);
  this.petrol = 100; 
};
// 继承原型,并修正constructor指向(避免原型链混乱)
PlayerShip.prototype = Object.create(Ship.prototype);
PlayerShip.prototype.constructor = PlayerShip;

// 子类EnemyShip同理处理
function EnemyShip(x, y) { 
  Ship.call(this, x, y);
  this.color = 'red'; 
};
EnemyShip.prototype = Object.create(Ship.prototype);
EnemyShip.prototype.constructor = EnemyShip;

player = new PlayerShip(100, 100);
for(var i = 0; i < enemiesCntInit; i++) { 
  enemies.push(new EnemyShip(0, 0)); 
}

console.log(player); // 现在会包含xCoord:100, yCoord:100, petrol:100
console.log(enemies); // 每个EnemyShip实例都有xCoord:0, yCoord:0, color:'red'

如何实现抽象构造函数

抽象构造函数的核心是禁止直接实例化,只能作为父类被继承。在ES5中可以通过检查当前实例的构造函数是否为抽象类本身来实现:

function Ship(x, y) {
  // 如果直接new Ship(),抛出错误阻止实例化
  if (this.constructor === Ship) {
    throw new Error('Ship是抽象构造函数,不能直接实例化,请继承后使用');
  }
  this.xCoord = x;
  this.yCoord = y;
}

// 测试:直接实例化会报错
// var ship = new Ship(50,50); // 抛出Error

// 子类正常继承并实例化
function PlayerShip(x, y) {
  Ship.call(this, x, y);
  this.petrol = 100;
}
PlayerShip.prototype = Object.create(Ship.prototype);
PlayerShip.prototype.constructor = PlayerShip;

var player = new PlayerShip(100,100); // 正常工作

如果用ES6 Class语法,实现抽象类会更直观,通过new.target判断当前调用构造函数的是否为抽象类本身:

class Ship {
  constructor(x, y) {
    if (new.target === Ship) {
      throw new Error('Ship是抽象类,不能直接实例化');
    }
    this.xCoord = x;
    this.yCoord = y;
  }
}

class PlayerShip extends Ship {
  constructor(x, y) {
    super(x, y); // ES6中用super调用父类构造函数
    this.petrol = 100;
  }
}

// new Ship(); // 报错
const player = new PlayerShip(100,100); // 正常创建实例

这样就保证了Ship只能被继承,不能直接创建实例,符合抽象构造函数的设计要求。

内容的提问来源于stack exchange,提问作者provoter33

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:54:25