继承与多态

在面向对象编程中,继承多态是实现代码复用和行为扩展的核心机制。以"动物世界"为隐喻,我们可以直观理解这两个概念的工作原理及其在 TypeScript 中的应用。

一、继承:代码复用与扩展

继承允许子类(派生类)复用父类(基类)的属性和方法,并在此基础上添加新功能或重写现有功能。TypeScript 中通过 extends 关键字声明继承关系,通过 super 关键字调用父类的构造函数或方法。

继承核心语法

  • extends:声明子类继承自父类,如 class Dog extends Animal 表示 DogAnimal 的子类
  • super:在子类中调用父类的方法或构造函数,如 super.move(distance) 调用父类 Animalmove 方法

示例:动物与狗的继承关系
定义父类 Animal 封装通用行为(移动),子类 Dog 继承该行为并添加特有功能(吠叫):

typescript
复制代码
// 父类:动物
class Animal {
  move(distance: number): void {
    console.log(`Moved ${distance}m`); // 通用移动行为
  }
}

// 子类:狗(继承自动物)
class Dog extends Animal {
  // 子类特有方法
  bark(): void {
    console.log('Woof!');
  }

  // 重写父类方法(扩展行为)
  move(distance: number): void {
    super.move(distance); // 调用父类 move 方法
    this.bark(); // 添加子类特有行为
  }
}

// 使用:Dog 实例同时拥有 move 和 bark 方法
const dog = new Dog();
dog.move(10); // 输出:"Moved 10m" 和 "Woof!"

在上述示例中,Dog 类通过继承获得了 Animalmove 方法,并通过重写该方法实现了"移动后吠叫"的个性化行为,体现了继承的扩展性

二、多态:同一方法的不同实现

多态是指同一方法在不同对象上表现出不同行为的特性。当子类重写父类方法后,通过父类类型的引用调用该方法时,会动态绑定到子类的实现,从而实现"接口统一,实现各异"。

示例:动物移动的多态表现
定义一个接收 Animal 类型参数的函数,传入不同子类实例时,会执行各自的 move 实现:

typescript
复制代码
// 多态函数:接收 Animal 类型,调用 move 方法
function letAnimalMove(animal: Animal): void {
  animal.move(10); // 调用的是子类重写后的 move 方法
}

// 新增 Cat 类(继承 Animal 并重写 move)
class Cat extends Animal {
  move(distance: number): void {
    console.log(`Cat moved ${distance}m silently`); // 猫的移动行为
  }
}

// 多态体现:同一函数,不同对象表现不同
letAnimalMove(new Dog()); // 输出:"Moved 10m" 和 "Woof!"(Dog 的 move)
letAnimalMove(new Cat()); // 输出:"Cat moved 10m silently"(Cat 的 move)

此处,letAnimalMove 函数无需关心传入的具体动物类型,只需调用 move 方法即可,具体行为由子类实例决定,这体现了多态的灵活性

三、实际应用:前端组件继承

在前端开发中,组件继承是多态的典型应用。例如 React 类组件中,自定义组件通过继承 Component 基类并重写 render 方法,实现个性化 UI 展示:

typescript
复制代码
// 基类:React 组件
class Component {
  render(): string {
    return '<div>Default Component</div>'; // 默认渲染内容
  }
}

// 子类:自定义按钮组件
class Button extends Component {
  // 重写 render 方法,实现自定义样式
  render(): string {
    return '<button style="background: blue; color: white">Custom Button</button>';
  }
}

// 使用:Button 实例渲染自定义内容
const button = new Button();
console.log(button.render()); // 输出自定义按钮 HTML

通过重写 render 方法,Button 组件在复用 Component 基础功能的同时,实现了独特的视觉表现,这是多态在 UI 开发中的直接体现。

四、实践练习:形状面积计算

目标:定义"形状"抽象类,子类(圆形、矩形)实现面积计算方法,体现多态。

步骤提示

  1. 定义抽象类 Shape,包含抽象方法 getArea()(无需实现)
  2. 实现子类 Circle(半径)和 Rectangle(长、宽),分别实现 getArea()
  3. 创建多态函数,接收 Shape 类型参数并调用 getArea(),验证不同形状的面积计算结果

参考实现框架

typescript
复制代码
// 抽象类:形状(定义接口规范)
abstract class Shape {
  abstract getArea(): number; // 抽象方法,子类必须实现
}

// 圆形(实现 Shape)
class Circle extends Shape {
  constructor(private radius: number) {
    super();
  }

  getArea(): number {
    return Math.PI * this.radius ** 2; // 圆面积公式:πr²
  }
}

// 矩形(实现 Shape)
class Rectangle extends Shape {
  constructor(private width: number, private height: number) {
    super();
  }

  getArea(): number {
    return this.width * this.height; // 矩形面积公式:长×宽
  }
}

// 多态函数:计算任意形状的面积
function calculateArea(shape: Shape): void {
  console.log(`Area: ${shape.getArea().toFixed(2)}`);
}

// 测试:多态调用
calculateArea(new Circle(5)); // 输出:"Area: 78.54"(π×5²)
calculateArea(new Rectangle(4, 6)); // 输出:"Area: 24.00"(4×6)

通过该练习,可以清晰理解抽象类定义接口规范子类实现具体逻辑多态函数统一调用的完整流程,掌握继承与多态的协同应用。

继承与多态的结合,不仅实现了代码复用,更通过"接口标准化,实现差异化"提升了系统的灵活性和可扩展性。在 TypeScript 开发中,合理运用这两个特性,能够构建出更易于维护和扩展的面向对象系统。