Menu
CoddyTech

深层继承的局限

本课属于 Coddy JavaScript 学习旅程的“面向对象编程”单元。第 48 课,共 56 课。

虽然继承很有用,但创建非常深的继承层级(父类 → 子类 → 孙类 → 曾孙类)可能会带来问题。继承链越深,代码就越难理解、维护和修改。

来看看多层继承链会发生什么:

// 基类
class Vehicle {
  constructor(type) {
    this.type = type;
    this.isRunning = false;
  }
  
  start() {
    this.isRunning = true;
    console.log(`${this.type} started`);
  }
}

// 第一层继承
class Car extends Vehicle {
  constructor(make, model) {
    super("Car");
    this.make = make;
    this.model = model;
    this.wheels = 4;
  }
  
  honk() {
    console.log("Beep beep!");
  }
}

// 第二层继承
class SportsCar extends Car {
  constructor(make, model, topSpeed) {
    super(make, model);
    this.topSpeed = topSpeed;
  }
  
  race() {
    this.start();
    console.log(`Racing at ${this.topSpeed} mph!`);
  }
}

在这个示例中,SportsCar 的继承层级有两层。这可能会导致一些问题:

  1. 对 Vehicle 的更改可能会意外地导致 SportsCar 出现问题
  1. 随着继承链变长,追踪方法和属性的来源会变得更困难
  1. 你会被迫使用“是一个”关系,而这种关系可能不够灵活
challenge icon

挑战

完成 Robot.js 文件,让机器人能够正常工作。现在机器人已经构建完成,但还什么也做不了。

Robot.js 中要做的事:

  1. 创建 speaker 和 mover 组件,并将它们放在 Robot 构造函数中
  2. 在方法中使用这些组件:
    1. 在 greet() 中:调用 this.speaker.speak("Hello!");
    2. 在 walkForward() 中:调用 this.mover.move("forward");

这样做的原因:这就是组合,机器人由更小的组件组合而成。机器人拥有一个 speaker(用于说话)和一个 mover(用于移动),而不是通过继承获得这些能力。

亲手试试

import { Robot } from './Robot.js';

const myRobot = new Robot('Robo');

myRobot.greet();     // 应输出:Saying: "Hello!"
myRobot.walkForward(); // 应输出:Moving forward
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: JavaScript 在线编译器