Skip to content

JavaScript 类继承

继承是面向对象编程的核心概念之一,它允许我们创建新的类来扩展现有类的功能。JavaScript 通过 extends 关键字支持类继承,使得代码重用和层次化设计变得更加容易。在本章节中,我们将深入学习 JavaScript 中的类继承机制。

什么是继承

继承允许一个类(子类)获取另一个类(父类)的属性和方法。这种机制提供了以下优势:

  1. 代码重用:避免重复编写相同的代码
  2. 层次化设计:建立清晰的类层次结构
  3. 扩展性:可以在不修改原有代码的情况下扩展功能
  4. 多态性:同一接口可以有不同的实现

基本继承语法

extends 关键字

javascript
// 父类(基类)
class Animal {
  constructor(name, species) {
    this.name = name;
    this.species = species;
  }
  
  speak() {
    return `${this.name} 发出声音`;
  }
  
  move() {
    return `${this.name} 在移动`;
  }
  
  getInfo() {
    return `我是${this.species},名叫${this.name}`;
  }
}

// 子类(派生类)
class Dog extends Animal {
  constructor(name, breed) {
    super(name, "狗"); // 调用父类构造函数
    this.breed = breed;
  }
  
  // 重写父类方法
  speak() {
    return `${this.name} 汪汪叫`;
  }
  
  // 子类特有方法
  fetch() {
    return `${this.name} 去捡球`;
  }
  
  // 扩展父类方法
  getInfo() {
    return `${super.getInfo()},品种是${this.breed}`;
  }
}

class Cat extends Animal {
  constructor(name, color) {
    super(name, "猫");
    this.color = color;
  }
  
  speak() {
    return `${this.name} 喵喵叫`;
  }
  
  climb() {
    return `${this.name} 爬树`;
  }
  
  getInfo() {
    return `${super.getInfo()},毛色是${this.color}`;
  }
}

// 使用示例
const dog = new Dog("旺财", "金毛");
const cat = new Cat("咪咪", "橘色");

console.log(dog.speak()); // "旺财 汪汪叫"
console.log(dog.move()); // "旺财 在移动"(继承自父类)
console.log(dog.fetch()); // "旺财 去捡球"
console.log(dog.getInfo()); // "我是狗,名叫旺财,品种是金毛"

console.log(cat.speak()); // "咪咪 喵喵叫"
console.log(cat.climb()); // "咪咪 爬树"
console.log(cat.getInfo()); // "我是猫,名叫咪咪,毛色是橘色"

super 关键字

调用父类构造函数

javascript
class Vehicle {
  constructor(brand, model, year) {
    this.brand = brand;
    this.model = model;
    this.year = year;
    this.isRunning = false;
  }
  
  start() {
    this.isRunning = true;
    return `${this.brand} ${this.model} 启动了`;
  }
  
  stop() {
    this.isRunning = false;
    return `${this.brand} ${this.model} 停止了`;
  }
  
  getInfo() {
    return `${this.year} ${this.brand} ${this.model}`;
  }
}

class Car extends Vehicle {
  constructor(brand, model, year, doors) {
    super(brand, model, year); // 必须在使用 this 之前调用
    this.doors = doors;
    this.fuel = 100;
  }
  
  drive(distance) {
    if (!this.isRunning) {
      return "请先启动车辆";
    }
    
    const fuelConsumed = distance * 0.1;
    if (this.fuel < fuelConsumed) {
      return "燃油不足";
    }
    
    this.fuel -= fuelConsumed;
    return `行驶了 ${distance} 公里,剩余燃油 ${this.fuel.toFixed(1)}%`;
  }
  
  refuel(amount) {
    this.fuel = Math.min(100, this.fuel + amount);
    return `加油 ${amount}%,当前燃油 ${this.fuel}%`;
  }
  
  getInfo() {
    return `${super.getInfo()} (${this.doors}门)`;
  }
}

class Motorcycle extends Vehicle {
  constructor(brand, model, year, engineSize) {
    super(brand, model, year);
    this.engineSize = engineSize; // cc
    this.speed = 0;
  }
  
  accelerate(speed) {
    if (!this.isRunning) {
      return "请先启动车辆";
    }
    
    this.speed = Math.min(200, speed);
    return `加速到 ${this.speed} km/h`;
  }
  
  brake() {
    this.speed = 0;
    return "刹车";
  }
  
  getInfo() {
    return `${super.getInfo()} (${this.engineSize}cc)`;
  }
}

// 使用示例
const car = new Car("丰田", "卡罗拉", 2023, 4);
console.log(car.start()); // "丰田 卡罗拉 启动了"
console.log(car.drive(50)); // "行驶了 50 公里,剩余燃油 95.0%"
console.log(car.refuel(10)); // "加油 10%,当前燃油 100%"
console.log(car.getInfo()); // "2023 丰田 卡罗拉 (4门)"

const motorcycle = new Motorcycle("本田", "CBR", 2023, 600);
console.log(motorcycle.start()); // "本田 CBR 启动了"
console.log(motorcycle.accelerate(120)); // "加速到 120 km/h"
console.log(motorcycle.brake()); // "刹车"
console.log(motorcycle.getInfo()); // "2023 本田 CBR (600cc)"

调用父类方法

javascript
class Shape {
  constructor(color) {
    this.color = color;
  }
  
  getArea() {
    return 0;
  }
  
  getPerimeter() {
    return 0;
  }
  
  getDescription() {
    return `这是一个${this.color}的图形`;
  }
  
  getInfo() {
    return {
      type: this.constructor.name,
      color: this.color,
      area: this.getArea(),
      perimeter: this.getPerimeter()
    };
  }
}

class Rectangle extends Shape {
  constructor(color, width, height) {
    super(color);
    this.width = width;
    this.height = height;
  }
  
  getArea() {
    return this.width * this.height;
  }
  
  getPerimeter() {
    return 2 * (this.width + this.height);
  }
  
  getDescription() {
    return `${super.getDescription()},尺寸为 ${this.width}x${this.height}`;
  }
  
  isSquare() {
    return this.width === this.height;
  }
}

class Circle extends Shape {
  constructor(color, radius) {
    super(color);
    this.radius = radius;
  }
  
  getArea() {
    return Math.PI * this.radius * this.radius;
  }
  
  getPerimeter() {
    return 2 * Math.PI * this.radius;
  }
  
  getDescription() {
    return `${super.getDescription()},半径为 ${this.radius}`;
  }
  
  getDiameter() {
    return this.radius * 2;
  }
}

// 使用示例
const rectangle = new Rectangle("红色", 10, 5);
const circle = new Circle("蓝色", 3);

console.log(rectangle.getDescription()); 
// "这是一个红色的图形,尺寸为 10x5"
console.log(rectangle.getInfo());
// { type: "Rectangle", color: "红色", area: 50, perimeter: 30 }

console.log(circle.getDescription()); 
// "这是一个蓝色的图形,半径为 3"
console.log(circle.getInfo());
// { type: "Circle", color: "蓝色", area: 28.274333882308138, perimeter: 18.84955592153876 }

多层继承

javascript
// 基类
class Animal {
  constructor(name) {
    this.name = name;
    this.energy = 100;
  }
  
  eat(food) {
    this.energy += 10;
    return `${this.name} 吃了 ${food},能量增加到 ${this.energy}`;
  }
  
  sleep() {
    this.energy = 100;
    return `${this.name} 睡觉了,能量恢复到 ${this.energy}`;
  }
  
  getInfo() {
    return `${this.name} (能量: ${this.energy})`;
  }
}

// 第一层继承
class Mammal extends Animal {
  constructor(name, furColor) {
    super(name);
    this.furColor = furColor;
    this.bodyTemperature = 37;
  }
  
  regulateTemperature() {
    return `${this.name} 调节体温到 ${this.bodyTemperature}°C`;
  }
  
  getInfo() {
    return `${super.getInfo()} [哺乳动物,毛色: ${this.furColor}]`;
  }
}

// 第二层继承
class Dog extends Mammal {
  constructor(name, furColor, breed) {
    super(name, furColor);
    this.breed = breed;
    this.tricks = [];
  }
  
  bark() {
    this.energy -= 5;
    return `${this.name} 汪汪叫 (能量: ${this.energy})`;
  }
  
  learnTrick(trick) {
    this.tricks.push(trick);
    return `${this.name} 学会了 ${trick}`;
  }
  
  performTrick() {
    if (this.tricks.length === 0) {
      return `${this.name} 还没有学会任何技巧`;
    }
    
    if (this.energy < 20) {
      return `${this.name} 太累了,需要休息`;
    }
    
    const trick = this.tricks[Math.floor(Math.random() * this.tricks.length)];
    this.energy -= 20;
    return `${this.name} 表演了 ${trick} (能量: ${this.energy})`;
  }
  
  getInfo() {
    return `${super.getInfo()} [品种: ${this.breed}, 技巧: ${this.tricks.join(", ")}]`;
  }
}

// 第二层继承
class Cat extends Mammal {
  constructor(name, furColor, pattern) {
    super(name, furColor);
    this.pattern = pattern;
    this.lives = 9;
  }
  
  meow() {
    this.energy -= 3;
    return `${this.name} 喵喵叫 (能量: ${this.energy})`;
  }
  
  climb() {
    if (this.energy < 15) {
      return `${this.name} 太累了,无法爬树`;
    }
    
    this.energy -= 15;
    return `${this.name} 爬上了树 (能量: ${this.energy})`;
  }
  
  loseLife() {
    if (this.lives > 0) {
      this.lives--;
      this.energy = 100; // 复活后恢复能量
      return `${this.name} 失去了一条命,还剩 ${this.lives} 条命`;
    }
    return `${this.name} 已经没有命了`;
  }
  
  getInfo() {
    return `${super.getInfo()} [花纹: ${this.pattern}, 剩余生命: ${this.lives}]`;
  }
}

// 使用示例
const dog = new Dog("旺财", "金色", "金毛");
const cat = new Cat("咪咪", "灰色", "条纹");

console.log(dog.eat("狗粮")); // "旺财 吃了 狗粮,能量增加到 110"
console.log(dog.bark()); // "旺财 汪汪叫 (能量: 105)"
console.log(dog.learnTrick("握手")); // "旺财 学会了 握手"
console.log(dog.learnTrick("坐下")); // "旺财 学会了 坐下"
console.log(dog.performTrick()); // "旺财 表演了 握手 (能量: 85)"

console.log(cat.eat("鱼")); // "咪咪 吃了 鱼,能量增加到 110"
console.log(cat.meow()); // "咪咪 喵喵叫 (能量: 107)"
console.log(cat.climb()); // "咪咪 爬上了树 (能量: 92)"

console.log(dog.getInfo());
console.log(cat.getInfo());

方法重写和多态

方法重写

javascript
class PaymentMethod {
  constructor(name) {
    this.name = name;
  }
  
  processPayment(amount) {
    return `使用 ${this.name} 支付 ¥${amount}`;
  }
  
  validate() {
    return true;
  }
  
  getFee(amount) {
    return 0;
  }
}

class CreditCard extends PaymentMethod {
  constructor(name, cardNumber) {
    super(name);
    this.cardNumber = cardNumber;
    this.limit = 50000;
    this.balance = 0;
  }
  
  // 重写父类方法
  processPayment(amount) {
    if (!this.validate()) {
      throw new Error("支付验证失败");
    }
    
    const totalAmount = amount + this.getFee(amount);
    
    if (this.balance + totalAmount > this.limit) {
      throw new Error("超出信用额度");
    }
    
    this.balance += totalAmount;
    return `信用卡支付成功: ¥${amount} (手续费: ¥${this.getFee(amount)})`;
  }
  
  validate() {
    // 简化的信用卡验证
    return this.cardNumber && this.cardNumber.length === 16;
  }
  
  getFee(amount) {
    return amount * 0.02; // 2% 手续费
  }
  
  getAvailableCredit() {
    return this.limit - this.balance;
  }
}

class Alipay extends PaymentMethod {
  constructor(name, account) {
    super(name);
    this.account = account;
    this.balance = 10000; // 账户余额
  }
  
  processPayment(amount) {
    if (!this.validate()) {
      throw new Error("支付验证失败");
    }
    
    const totalAmount = amount + this.getFee(amount);
    
    if (this.balance < totalAmount) {
      throw new Error("余额不足");
    }
    
    this.balance -= totalAmount;
    return `支付宝支付成功: ¥${amount} (手续费: ¥${this.getFee(amount)})`;
  }
  
  validate() {
    return this.account && this.account.includes("@");
  }
  
  getFee(amount) {
    return amount > 2000 ? amount * 0.001 : 0; // 超过2000元收0.1%手续费
  }
  
  recharge(amount) {
    this.balance += amount;
    return `充值成功: ¥${amount},当前余额: ¥${this.balance}`;
  }
}

class WeChatPay extends PaymentMethod {
  constructor(name, openid) {
    super(name);
    this.openid = openid;
    this.balance = 8000;
  }
  
  processPayment(amount) {
    if (!this.validate()) {
      throw new Error("支付验证失败");
    }
    
    const totalAmount = amount + this.getFee(amount);
    
    if (this.balance < totalAmount) {
      throw new Error("余额不足");
    }
    
    this.balance -= totalAmount;
    return `微信支付成功: ¥${amount} (手续费: ¥${this.getFee(amount)})`;
  }
  
  validate() {
    return this.openid && this.openid.length > 10;
  }
  
  getFee(amount) {
    return 0; // 微信支付通常无手续费
  }
  
  transfer(toUser, amount) {
    if (this.balance < amount) {
      throw new Error("余额不足");
    }
    
    this.balance -= amount;
    return `转账成功: 向 ${toUser} 转账 ¥${amount}`;
  }
}

// 使用示例
const creditCard = new CreditCard("Visa信用卡", "1234567890123456");
const alipay = new Alipay("支付宝", "user@example.com");
const wechat = new WeChatPay("微信支付", "openid_1234567890");

// 多态性:同一接口,不同实现
const payments = [creditCard, alipay, wechat];

payments.forEach(payment => {
  try {
    console.log(payment.processPayment(1000));
  } catch (error) {
    console.log(`${payment.name}: ${error.message}`);
  }
});

// 特定方法调用
console.log(creditCard.getAvailableCredit());
console.log(alipay.recharge(5000));
console.log(wechat.transfer("朋友A", 200));

继承中的静态方法

javascript
class Database {
  constructor(name) {
    this.name = name;
    this.isConnected = false;
  }
  
  connect() {
    this.isConnected = true;
    return `连接到数据库 ${this.name}`;
  }
  
  disconnect() {
    this.isConnected = false;
    return `断开数据库 ${this.name} 连接`;
  }
  
  // 静态方法
  static getDefaultConfig() {
    return {
      host: "localhost",
      port: 3306,
      timeout: 5000
    };
  }
  
  static validateConfig(config) {
    return config.host && config.port;
  }
  
  // 静态属性(ES2022)
  static VERSION = "1.0.0";
}

class MySQL extends Database {
  constructor(name, config) {
    super(name);
    this.config = { ...Database.getDefaultConfig(), ...config };
  }
  
  connect() {
    if (!Database.validateConfig(this.config)) {
      throw new Error("数据库配置无效");
    }
    
    return `${super.connect()} [MySQL ${MySQL.VERSION}]`;
  }
  
  query(sql) {
    if (!this.isConnected) {
      throw new Error("数据库未连接");
    }
    
    return `执行查询: ${sql}`;
  }
  
  // 重写静态方法
  static getDefaultConfig() {
    return {
      ...super.getDefaultConfig(),
      engine: "InnoDB",
      charset: "utf8mb4"
    };
  }
  
  static validateConfig(config) {
    return super.validateConfig(config) && config.engine;
  }
}

class PostgreSQL extends Database {
  constructor(name, config) {
    super(name);
    this.config = { ...Database.getDefaultConfig(), ...config };
  }
  
  connect() {
    if (!Database.validateConfig(this.config)) {
      throw new Error("数据库配置无效");
    }
    
    return `${super.connect()} [PostgreSQL ${PostgreSQL.VERSION}]`;
  }
  
  execute(sql) {
    if (!this.isConnected) {
      throw new Error("数据库未连接");
    }
    
    return `执行语句: ${sql}`;
  }
  
  static getDefaultConfig() {
    return {
      ...super.getDefaultConfig(),
      dialect: "postgres",
      pool: { max: 10, min: 0 }
    };
  }
  
  static validateConfig(config) {
    return super.validateConfig(config) && config.dialect;
  }
}

// 使用示例
console.log("数据库版本:", Database.VERSION); // "1.0.0"

const mysqlConfig = {
  host: "localhost",
  port: 3306,
  engine: "InnoDB"
};

const pgConfig = {
  host: "localhost",
  port: 5432,
  dialect: "postgres"
};

const mysql = new MySQL("myapp", mysqlConfig);
const postgres = new PostgreSQL("myapp", pgConfig);

console.log(mysql.connect()); // "连接到数据库 myapp [MySQL 1.0.0]"
console.log(mysql.query("SELECT * FROM users")); // "执行查询: SELECT * FROM users"

console.log(postgres.connect()); // "连接到数据库 myapp [PostgreSQL 1.0.0]"
console.log(postgres.execute("SELECT * FROM users")); // "执行语句: SELECT * FROM users"

// 静态方法调用
console.log("MySQL默认配置:", MySQL.getDefaultConfig());
console.log("PostgreSQL默认配置:", PostgreSQL.getDefaultConfig());

继承最佳实践

1. 合理设计继承层次

javascript
// 好的设计:清晰的继承层次
class Vehicle {
  constructor(brand) {
    this.brand = brand;
  }
  
  start() {
    return `${this.brand} 启动`;
  }
}

class LandVehicle extends Vehicle {
  constructor(brand, wheels) {
    super(brand);
    this.wheels = wheels;
  }
  
  drive() {
    return `${this.brand} 在路上行驶`;
  }
}

class WaterVehicle extends Vehicle {
  constructor(brand, displacement) {
    super(brand);
    this.displacement = displacement; // 排水量
  }
  
  sail() {
    return `${this.brand} 在水上航行`;
  }
}

class Car extends LandVehicle {
  constructor(brand, doors) {
    super(brand, 4);
    this.doors = doors;
  }
  
  park() {
    return `${this.brand} 停车`;
  }
}

class Motorcycle extends LandVehicle {
  constructor(brand, engineType) {
    super(brand, 2);
    this.engineType = engineType;
  }
  
  wheelie() {
    return `${this.brand} 后轮着地`;
  }
}

class Boat extends WaterVehicle {
  constructor(brand, type) {
    super(brand, "中等");
    this.type = type; // 艇型
  }
  
  anchor() {
    return `${this.brand} 抛锚`;
  }
}

// 使用示例
const car = new Car("丰田", 4);
const motorcycle = new Motorcycle("本田", "四冲程");
const boat = new Boat("游艇品牌", "游艇");

console.log(car.start()); // "丰田 启动"
console.log(car.drive()); // "丰田 在路上行驶"
console.log(car.park()); // "丰田 停车"

console.log(motorcycle.start()); // "本田 启动"
console.log(motorcycle.drive()); // "本田 在路上行驶"
console.log(motorcycle.wheelie()); // "本田 后轮着地"

console.log(boat.start()); // "游艇品牌 启动"
console.log(boat.sail()); // "游艇品牌 在水上航行"
console.log(boat.anchor()); // "游艇品牌 抛锚"

2. 使用组合优于继承

javascript
// 继承方式(不太灵活)
class SmartPhone extends Phone {
  constructor(brand, model) {
    super(brand, model);
    this.apps = [];
    this.battery = 100;
  }
  
  installApp(app) {
    this.apps.push(app);
    return `安装应用: ${app}`;
  }
  
  runApp(app) {
    if (this.battery < 10) {
      return "电量不足";
    }
    
    this.battery -= 5;
    return `运行应用: ${app}`;
  }
  
  charge() {
    this.battery = 100;
    return "充电完成";
  }
}

// 组合方式(更灵活)
class Device {
  constructor(brand, model) {
    this.brand = brand;
    this.model = model;
  }
  
  powerOn() {
    return `${this.brand} ${this.model} 开机`;
  }
  
  powerOff() {
    return `${this.brand} ${this.model} 关机`;
  }
}

class Battery {
  constructor(capacity = 100) {
    this.capacity = capacity;
    this.level = capacity;
  }
  
  use(amount) {
    this.level = Math.max(0, this.level - amount);
  }
  
  charge() {
    this.level = this.capacity;
  }
  
  getLevel() {
    return this.level;
  }
  
  isLow() {
    return this.level < 20;
  }
}

class AppManager {
  constructor() {
    this.installedApps = [];
  }
  
  install(app) {
    this.installedApps.push(app);
    return `安装应用: ${app}`;
  }
  
  uninstall(app) {
    this.installedApps = this.installedApps.filter(a => a !== app);
    return `卸载应用: ${app}`;
  }
  
  getInstalledApps() {
    return [...this.installedApps];
  }
}

class SmartPhone {
  constructor(brand, model) {
    this.device = new Device(brand, model);
    this.battery = new Battery(100);
    this.appManager = new AppManager();
  }
  
  powerOn() {
    return this.device.powerOn();
  }
  
  powerOff() {
    return this.device.powerOff();
  }
  
  installApp(app) {
    return this.appManager.install(app);
  }
  
  runApp(app) {
    if (this.battery.isLow()) {
      return "电量不足,请充电";
    }
    
    this.battery.use(5);
    return `运行应用: ${app}`;
  }
  
  charge() {
    this.battery.charge();
    return "充电完成";
  }
  
  getBatteryLevel() {
    return this.battery.getLevel();
  }
  
  getInstalledApps() {
    return this.appManager.getInstalledApps();
  }
}

// 使用示例
const phone = new SmartPhone("苹果", "iPhone 15");

console.log(phone.powerOn()); // "苹果 iPhone 15 开机"
console.log(phone.installApp("微信")); // "安装应用: 微信"
console.log(phone.installApp("支付宝")); // "安装应用: 支付宝"
console.log(phone.runApp("微信")); // "运行应用: 微信"
console.log(phone.getBatteryLevel()); // 95
console.log(phone.getInstalledApps()); // ["微信", "支付宝"]
console.log(phone.charge()); // "充电完成"

3. 抽象类和接口模拟

javascript
// 抽象类(模拟)
class Animal {
  constructor(name) {
    if (this.constructor === Animal) {
      throw new Error("不能直接实例化抽象类 Animal");
    }
    this.name = name;
  }
  
  // 抽象方法(需要子类实现)
  makeSound() {
    throw new Error("抽象方法 makeSound 必须被子类实现");
  }
  
  // 具体方法
  eat() {
    return `${this.name} 在吃东西`;
  }
  
  sleep() {
    return `${this.name} 在睡觉`;
  }
}

class Dog extends Animal {
  constructor(name) {
    super(name);
  }
  
  // 实现抽象方法
  makeSound() {
    return `${this.name} 汪汪叫`;
  }
  
  // 特有方法
  fetch() {
    return `${this.name} 去捡球`;
  }
}

class Cat extends Animal {
  constructor(name) {
    super(name);
  }
  
  // 实现抽象方法
  makeSound() {
    return `${this.name} 喵喵叫`;
  }
  
  // 特有方法
  climb() {
    return `${this.name} 爬树`;
  }
}

// 接口模拟
class Flyable {
  fly() {
    throw new Error("fly 方法必须被实现");
  }
}

class Swimmable {
  swim() {
    throw new Error("swim 方法必须被实现");
  }
}

// 多重继承模拟(通过混入)
class Bird extends Animal {
  constructor(name) {
    super(name);
  }
  
  makeSound() {
    return `${this.name} 唧唧喳喳`;
  }
}

// 混入 Flyable 功能
Object.assign(Bird.prototype, Flyable.prototype);
Bird.prototype.fly = function() {
  return `${this.name} 在天空中飞翔`;
};

class Fish extends Animal {
  constructor(name) {
    super(name);
  }
  
  makeSound() {
    return `${this.name} 吐泡泡`;
  }
}

// 混入 Swimmable 功能
Object.assign(Fish.prototype, Swimmable.prototype);
Fish.prototype.swim = function() {
  return `${this.name} 在水中游泳`;
};

class Duck extends Animal {
  constructor(name) {
    super(name);
  }
  
  makeSound() {
    return `${this.name} 嘎嘎叫`;
  }
}

// 混入多个接口
Object.assign(Duck.prototype, Flyable.prototype, Swimmable.prototype);
Duck.prototype.fly = function() {
  return `${this.name} 飞起来了`;
};

Duck.prototype.swim = function() {
  return `${this.name} 在水中游泳`;
};

// 使用示例
try {
  // const animal = new Animal("测试"); // 错误:不能直接实例化抽象类
} catch (error) {
  console.log(error.message);
}

const dog = new Dog("旺财");
const cat = new Cat("咪咪");
const bird = new Bird("小鸟");
const fish = new Fish("金鱼");
const duck = new Duck("唐老鸭");

console.log(dog.makeSound()); // "旺财 汪汪叫"
console.log(dog.fetch()); // "旺财 去捡球"

console.log(cat.makeSound()); // "咪咪 喵喵叫"
console.log(cat.climb()); // "咪咪 爬树"

console.log(bird.makeSound()); // "小鸟 唧唧喳喳"
console.log(bird.fly()); // "小鸟 在天空中飞翔"

console.log(fish.makeSound()); // "金鱼 吐泡泡"
console.log(fish.swim()); // "金鱼 在水中游泳"

console.log(duck.makeSound()); // "唐老鸭 嘎嘎叫"
console.log(duck.fly()); // "唐老鸭 飞起来了"
console.log(duck.swim()); // "唐老鸭 在水中游泳"

实际应用示例

1. 游戏角色系统

javascript
// 基础角色类
class Character {
  constructor(name, level = 1) {
    this.name = name;
    this.level = level;
    this.health = 100;
    this.maxHealth = 100;
    this.mana = 50;
    this.maxMana = 50;
    this.experience = 0;
    this.experienceToNextLevel = 100;
  }
  
  takeDamage(damage) {
    this.health = Math.max(0, this.health - damage);
    return `${this.name} 受到 ${damage} 点伤害,剩余生命值 ${this.health}`;
  }
  
  heal(amount) {
    this.health = Math.min(this.maxHealth, this.health + amount);
    return `${this.name} 恢复 ${amount} 点生命值`;
  }
  
  useMana(amount) {
    if (this.mana >= amount) {
      this.mana -= amount;
      return true;
    }
    return false;
  }
  
  restoreMana(amount) {
    this.mana = Math.min(this.maxMana, this.mana + amount);
  }
  
  gainExperience(exp) {
    this.experience += exp;
    
    if (this.experience >= this.experienceToNextLevel) {
      return this.levelUp();
    }
    
    return `${this.name} 获得 ${exp} 点经验值`;
  }
  
  levelUp() {
    this.level++;
    this.experience -= this.experienceToNextLevel;
    this.experienceToNextLevel = Math.floor(this.experienceToNextLevel * 1.5);
    
    this.maxHealth += 20;
    this.health = this.maxHealth;
    this.maxMana += 10;
    this.mana = this.maxMana;
    
    return `${this.name} 升级到 ${this.level} 级!`;
  }
  
  isAlive() {
    return this.health > 0;
  }
  
  getInfo() {
    return {
      name: this.name,
      level: this.level,
      health: this.health,
      maxHealth: this.maxHealth,
      mana: this.mana,
      maxMana: this.maxMana,
      experience: this.experience,
      experienceToNextLevel: this.experienceToNextLevel
    };
  }
}

// 战士类
class Warrior extends Character {
  constructor(name) {
    super(name);
    this.strength = 20;
    this.armor = 5;
  }
  
  // 基础攻击
  attack(target) {
    const damage = this.strength - target.armor;
    return target.takeDamage(Math.max(1, damage));
  }
  
  // 技能:重击
  heavyStrike(target) {
    const manaCost = 10;
    
    if (!this.useMana(manaCost)) {
      return `${this.name} 魔法值不足`;
    }
    
    const damage = (this.strength * 2) - target.armor;
    return target.takeDamage(Math.max(1, damage));
  }
  
  // 技能:防御姿态
  defend() {
    this.armor += 3;
    return `${this.name} 进入防御姿态,护甲增加`;
  }
  
  levelUp() {
    const result = super.levelUp();
    this.strength += 5;
    this.armor += 2;
    return result;
  }
  
  getInfo() {
    return {
      ...super.getInfo(),
      class: "战士",
      strength: this.strength,
      armor: this.armor
    };
  }
}

// 法师类
class Mage extends Character {
  constructor(name) {
    super(name);
    this.intelligence = 25;
    this.spellPower = 15;
  }
  
  // 基础攻击:火球术
  fireball(target) {
    const manaCost = 15;
    
    if (!this.useMana(manaCost)) {
      return `${this.name} 魔法值不足`;
    }
    
    const damage = this.spellPower + (this.intelligence * 0.5);
    return target.takeDamage(damage);
  }
  
  // 技能:治疗术
  healSpell(target) {
    const manaCost = 20;
    
    if (!this.useMana(manaCost)) {
      return `${this.name} 魔法值不足`;
    }
    
    const healAmount = this.intelligence;
    return target.heal(healAmount);
  }
  
  // 技能:魔法护盾
  magicShield() {
    const manaCost = 25;
    
    if (!this.useMana(manaCost)) {
      return `${this.name} 魔法值不足`;
    }
    
    this.armor += 10;
    return `${this.name} 施放魔法护盾`;
  }
  
  levelUp() {
    const result = super.levelUp();
    this.intelligence += 7;
    this.spellPower += 3;
    return result;
  }
  
  getInfo() {
    return {
      ...super.getInfo(),
      class: "法师",
      intelligence: this.intelligence,
      spellPower: this.spellPower
    };
  }
}

// 弓箭手类
class Archer extends Character {
  constructor(name) {
    super(name);
    this.dexterity = 18;
    this.criticalChance = 0.1; // 10% 暴击率
  }
  
  // 基础攻击:射击
  shoot(target) {
    let damage = this.dexterity;
    
    // 暴击计算
    if (Math.random() < this.criticalChance) {
      damage *= 2;
      return target.takeDamage(damage) + " (暴击!)";
    }
    
    return target.takeDamage(damage);
  }
  
  // 技能:多重射击
  multiShot(targets) {
    const manaCost = 20;
    
    if (!this.useMana(manaCost)) {
      return `${this.name} 魔法值不足`;
    }
    
    const results = [];
    const damage = this.dexterity * 0.7;
    
    targets.forEach(target => {
      results.push(target.takeDamage(damage));
    });
    
    return `${this.name} 发射多重箭:` + results.join(",");
  }
  
  // 技能:隐身
  stealth() {
    const manaCost = 15;
    
    if (!this.useMana(manaCost)) {
      return `${this.name} 魔法值不足`;
    }
    
    return `${this.name} 进入隐身状态`;
  }
  
  levelUp() {
    const result = super.levelUp();
    this.dexterity += 6;
    this.criticalChance += 0.02; // 增加暴击率
    return result;
  }
  
  getInfo() {
    return {
      ...super.getInfo(),
      class: "弓箭手",
      dexterity: this.dexterity,
      criticalChance: this.criticalChance
    };
  }
}

// 怪物类
class Monster extends Character {
  constructor(name, level, type) {
    super(name, level);
    this.type = type;
    this.expReward = level * 20;
    this.goldReward = level * 10;
    
    // 根据等级调整属性
    this.maxHealth = 50 + (level * 25);
    this.health = this.maxHealth;
    this.maxMana = 20 + (level * 10);
    this.mana = this.maxMana;
    this.strength = 10 + (level * 3);
    this.armor = level;
  }
  
  attack(target) {
    const damage = this.strength - target.armor;
    return target.takeDamage(Math.max(1, damage));
  }
  
  getInfo() {
    return {
      ...super.getInfo(),
      type: this.type,
      expReward: this.expReward,
      goldReward: this.goldReward
    };
  }
}

// 使用示例
const warrior = new Warrior("战士张三");
const mage = new Mage("法师李四");
const archer = new Archer("弓箭手王五");

const goblin = new Monster("哥布林", 1, "普通");
const orc = new Monster("兽人", 3, "精英");

// 战斗示例
console.log(warrior.attack(goblin));
console.log(mage.fireball(goblin));
console.log(archer.shoot(goblin));

if (!goblin.isAlive()) {
  console.log(warrior.gainExperience(goblin.expReward));
}

console.log(orc.attack(warrior));
console.log(warrior.heavyStrike(orc));
console.log(mage.healSpell(warrior));

console.log("战士信息:", warrior.getInfo());
console.log("法师信息:", mage.getInfo());
console.log("弓箭手信息:", archer.getInfo());

2. UI 组件系统

javascript
// 基础组件类
class Component {
  constructor(props = {}) {
    this.props = props;
    this.state = {};
    this.children = [];
    this.parent = null;
  }
  
  setState(newState) {
    this.state = { ...this.state, ...newState };
    this.render();
  }
  
  addChild(child) {
    child.parent = this;
    this.children.push(child);
  }
  
  removeChild(child) {
    const index = this.children.indexOf(child);
    if (index > -1) {
      this.children.splice(index, 1);
      child.parent = null;
    }
  }
  
  // 抽象方法,需要子类实现
  render() {
    throw new Error("render 方法必须被子类实现");
  }
  
  mount(container) {
    container.appendChild(this.render());
  }
}

// 容器组件
class Container extends Component {
  constructor(props) {
    super(props);
    this.style = props.style || {};
  }
  
  render() {
    const container = document.createElement(this.props.tagName || "div");
    
    // 应用样式
    Object.assign(container.style, this.style);
    
    // 渲染子组件
    this.children.forEach(child => {
      const childElement = child.render();
      container.appendChild(childElement);
    });
    
    return container;
  }
}

// 文本组件
class Text extends Component {
  constructor(props) {
    super(props);
    this.text = props.text || "";
  }
  
  render() {
    const textElement = document.createElement("span");
    textElement.textContent = this.text;
    
    if (this.props.className) {
      textElement.className = this.props.className;
    }
    
    return textElement;
  }
  
  updateText(newText) {
    this.text = newText;
    return this.render();
  }
}

// 按钮组件
class Button extends Component {
  constructor(props) {
    super(props);
    this.text = props.text || "按钮";
    this.disabled = props.disabled || false;
    this.onClick = props.onClick || (() => {});
  }
  
  render() {
    const button = document.createElement("button");
    button.textContent = this.text;
    button.disabled = this.disabled;
    
    if (this.props.className) {
      button.className = this.props.className;
    }
    
    // 绑定事件
    button.addEventListener("click", this.onClick);
    
    return button;
  }
  
  setDisabled(disabled) {
    this.disabled = disabled;
    return this.render();
  }
}

// 输入框组件
class Input extends Component {
  constructor(props) {
    super(props);
    this.value = props.value || "";
    this.placeholder = props.placeholder || "";
    this.type = props.type || "text";
    this.onInput = props.onInput || (() => {});
  }
  
  render() {
    const input = document.createElement("input");
    input.type = this.type;
    input.value = this.value;
    input.placeholder = this.placeholder;
    
    if (this.props.className) {
      input.className = this.props.className;
    }
    
    // 绑定事件
    input.addEventListener("input", (e) => {
      this.value = e.target.value;
      this.onInput(e);
    });
    
    return input;
  }
  
  getValue() {
    return this.value;
  }
  
  setValue(value) {
    this.value = value;
    return this.render();
  }
}

// 表单组件
class Form extends Container {
  constructor(props) {
    super({ ...props, tagName: "form" });
    this.onSubmit = props.onSubmit || ((e) => e.preventDefault());
  }
  
  render() {
    const form = super.render();
    form.addEventListener("submit", this.onSubmit);
    return form;
  }
  
  getData() {
    const data = {};
    
    // 收集所有输入组件的值
    this.children.forEach(child => {
      if (child instanceof Input && child.props.name) {
        data[child.props.name] = child.getValue();
      }
    });
    
    return data;
  }
}

// 卡片组件
class Card extends Container {
  constructor(props) {
    super(props);
    this.title = props.title || "";
  }
  
  render() {
    const card = document.createElement("div");
    card.className = "card";
    
    // 添加标题
    if (this.title) {
      const titleElement = document.createElement("h3");
      titleElement.textContent = this.title;
      card.appendChild(titleElement);
    }
    
    // 渲染子组件
    this.children.forEach(child => {
      const childElement = child.render();
      card.appendChild(childElement);
    });
    
    return card;
  }
}

// 使用示例
const app = new Container({
  style: {
    padding: "20px",
    fontFamily: "Arial, sans-serif"
  }
});

const title = new Text({
  text: "用户注册表单",
  className: "title"
});

const form = new Form({
  onSubmit: (e) => {
    e.preventDefault();
    const formData = form.getData();
    console.log("表单数据:", formData);
    submitButton.setDisabled(true);
  }
});

const nameInput = new Input({
  name: "name",
  placeholder: "请输入姓名",
  onInput: (e) => {
    console.log("姓名输入:", e.target.value);
  }
});

const emailInput = new Input({
  name: "email",
  type: "email",
  placeholder: "请输入邮箱"
});

const submitButton = new Button({
  text: "提交",
  onClick: () => {
    console.log("按钮被点击");
  }
});

// 组装界面
form.addChild(nameInput);
form.addChild(emailInput);
form.addChild(submitButton);

const card = new Card({
  title: "注册信息"
});
card.addChild(form);

app.addChild(title);
app.addChild(card);

// 模拟挂载到页面
// app.mount(document.body);

console.log("UI 组件系统示例创建完成");
console.log("组件层次结构:");
console.log("- Container (app)");
console.log("  - Text (title)");
console.log("  - Card (card)");
console.log("    - Form (form)");
console.log("      - Input (nameInput)");
console.log("      - Input (emailInput)");
console.log("      - Button (submitButton)");

总结

JavaScript 类继承的核心要点:

  1. 基本语法:使用 extends 关键字实现继承,super 调用父类
  2. 构造函数:子类构造函数中必须先调用 super() 再使用 this
  3. 方法重写:子类可以重写父类方法,使用 super 调用父类方法
  4. 多层继承:支持多层次的继承结构
  5. 静态继承:子类继承父类的静态方法和属性
  6. 多态性:同一接口可以有不同的实现
  7. 最佳实践:合理设计继承层次,优先使用组合而非继承
  8. 抽象类:通过抛出错误模拟抽象类和抽象方法

掌握类继承是面向对象编程的重要技能。在下一章节中,我们将学习 JavaScript 的静态方法。

本站内容仅供学习和研究使用。