在面向对象编程中,继承与多态是实现代码复用和行为扩展的核心机制。以"动物世界"为隐喻,我们可以直观理解这两个概念的工作原理及其在 TypeScript 中的应用。
继承允许子类(派生类)复用父类(基类)的属性和方法,并在此基础上添加新功能或重写现有功能。TypeScript 中通过 extends 关键字声明继承关系,通过 super 关键字调用父类的构造函数或方法。
继承核心语法
extends:声明子类继承自父类,如 class Dog extends Animal 表示 Dog 是 Animal 的子类 super:在子类中调用父类的方法或构造函数,如 super.move(distance) 调用父类 Animal 的 move 方法示例:动物与狗的继承关系
定义父类 Animal 封装通用行为(移动),子类 Dog 继承该行为并添加特有功能(吠叫):
// 父类:动物
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 类通过继承获得了 Animal 的 move 方法,并通过重写该方法实现了"移动后吠叫"的个性化行为,体现了继承的扩展性。
多态是指同一方法在不同对象上表现出不同行为的特性。当子类重写父类方法后,通过父类类型的引用调用该方法时,会动态绑定到子类的实现,从而实现"接口统一,实现各异"。
示例:动物移动的多态表现
定义一个接收 Animal 类型参数的函数,传入不同子类实例时,会执行各自的 move 实现:
// 多态函数:接收 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 展示:
// 基类: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 开发中的直接体现。
目标:定义"形状"抽象类,子类(圆形、矩形)实现面积计算方法,体现多态。
步骤提示
Shape,包含抽象方法 getArea()(无需实现) Circle(半径)和 Rectangle(长、宽),分别实现 getArea() Shape 类型参数并调用 getArea(),验证不同形状的面积计算结果参考实现框架:
// 抽象类:形状(定义接口规范)
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 开发中,合理运用这两个特性,能够构建出更易于维护和扩展的面向对象系统。