一、前言
随着前端项目的复杂度不断提升,良好的代码组织方式变得尤为重要。面向对象编程(Object-Oriented Programming, OOP) 是一种被广泛采用的程序设计范式,它通过“类”和“对象”的概念来构建模块化、可复用、易维护的代码结构。
TypeScript 在 JavaScript 的基础上引入了更强大的类型系统和面向对象特性,使得开发者能够以更加严谨和规范的方式编写大型应用。
本文将带你全面了解 TypeScript 中的面向对象编程特点,包括:
✅ 封装
✅ 继承
✅ 多态
✅ 抽象
✅ 接口与抽象类
✅ 访问修饰符
✅ 实际开发中的设计模式示例
并通过大量代码示例帮助你深入理解这些概念。
二、什么是面向对象编程?
✅ 定义:
面向对象编程是一种基于“对象”构建软件的方法,每个对象都是某个类的实例。类是数据(属性)和行为(方法)的封装体。
⚠️ 四大基本特征:
- 封装(Encapsulation)
- 继承(Inheritance)
- 多态(Polymorphism)
- 抽象(Abstraction)
三、TypeScript 中的类(Class)
TypeScript 的类支持构造函数、访问修饰符、静态成员、继承、抽象类等多种高级特性。
✅ 示例:基础类定义
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
sayHello(): void {
console.log(`Hello, my name is ${this.name}`);
}
}
const person = new Person("Alice");
person.sayHello(); // 输出:Hello, my name is Alice
四、封装(Encapsulation)
✅ 定义:
封装是指将数据和操作数据的方法绑定在一起,并对外隐藏实现细节。
✅ 示例:访问修饰符控制访问权限
| 修饰符 | 可见范围 |
|---|---|
public | 所有地方(默认) |
private | 仅本类内部 |
protected | 本类及子类 |
class BankAccount {
private balance: number = 0;
deposit(amount: number): void {
if (amount > 0) {
this.balance += amount;
}
}
getBalance(): number {
return this.balance;
}
}
const account = new BankAccount();
account.deposit(100);
console.log(account.getBalance()); // 输出:100
// console.log(account.balance); ❌ 错误:balance 是私有属性
五、继承(Inheritance)
✅ 定义:
继承是指一个类(子类)可以继承另一个类(父类)的属性和方法,从而实现代码复用。
✅ 示例:继承与重写
class Animal {
makeSound(): void {
console.log("Some sound");
}
}
class Dog extends Animal {
override makeSound(): void {
console.log("Woof!");
}
}
const dog = new Dog();
dog.makeSound(); // 输出:Woof!
六、多态(Polymorphism)
✅ 定义:
多态是指同一接口在不同对象中具有不同的实现方式。
✅ 示例:多态调用
function playSound(animal: Animal) {
animal.makeSound();
}
playSound(new Animal()); // Some sound
playSound(new Dog()); // Woof!
七、抽象(Abstraction)
✅ 定义:
抽象是指将复杂的实现细节隐藏起来,只暴露必要的接口供外部调用。
✅ 示例:抽象类与接口
abstract class Shape {
abstract getArea(): number;
}
class Rectangle extends Shape {
constructor(private width: number, private height: number) {
super();
}
getArea(): number {
return this.width * this.height;
}
}
八、接口(Interface)与抽象类(Abstract Class)
| 特性 | 接口(Interface) | 抽象类(Abstract Class) |
|---|---|---|
| 是否可以包含实现 | ❌ 否(TS 3.6+ 支持默认方法) | ✅ 是 |
| 是否支持构造函数 | ❌ 否 | ✅ 是 |
| 是否支持访问修饰符 | ✅ 是 | ✅ 是 |
| 是否可以多重继承 | ✅ 是(多个接口) | ❌ 否 |
| 是否用于共享逻辑 | ❌ 否 | ✅ 是 |
✅ 示例:接口实现
interface ILogger {
log(message: string): void;
}
class ConsoleLogger implements ILogger {
log(message: string): void {
console.log(`[LOG] ${message}`);
}
}
九、实际开发中的面向对象设计模式示例
✅ 场景1:工厂模式(Factory Pattern)
interface Product {
use(): void;
}
class ConcreteProductA implements Product {
use(): void {
console.log("Using Product A");
}
}
class ConcreteProductB implements Product {
use(): void {
console.log("Using Product B");
}
}
class ProductFactory {
static createProduct(type: string): Product {
switch (type) {
case "A":
return new ConcreteProductA();
case "B":
return new ConcreteProductB();
default:
throw new Error("Unknown product type");
}
}
}
const product = ProductFactory.createProduct("A");
product.use(); // 输出:Using Product A
✅ 场景2:策略模式(Strategy Pattern)
interface PaymentStrategy {
pay(amount: number): void;
}
class CreditCardPayment implements PaymentStrategy {
pay(amount: number): void {
console.log(`Paid $${amount} with Credit Card`);
}
}
class PayPalPayment implements PaymentStrategy {
pay(amount: number): void {
console.log(`Paid $${amount} with PayPal`);
}
}
class ShoppingCart {
constructor(private strategy: PaymentStrategy) {}
checkout(amount: number): void {
this.strategy.pay(amount);
}
}
const cart1 = new ShoppingCart(new CreditCardPayment());
cart1.checkout(100); // 输出:Paid $100 with Credit Card
const cart2 = new ShoppingCart(new PayPalPayment());
cart2.checkout(200); // 输出:Paid $200 with PayPal
十、JavaScript 原生类 vs TypeScript 类
| 特性 | JavaScript 类 | TypeScript 类 |
|---|---|---|
| 类型检查 | ❌ 无 | ✅ 强类型检查 |
| 接口 | ❌ 不支持 | ✅ 支持 |
| 抽象类 | ❌ 不支持 | ✅ 支持 |
| 访问修饰符 | ❌ 不支持 | ✅ 支持 |
| 默认参数值 | ✅ 支持 | ✅ 支持 |
| 静态方法 | ✅ 支持 | ✅ 支持 |
| 构造函数重载 | ❌ 不支持 | ✅ 支持(通过类型推断) |
十一、注意事项与最佳实践
| 场景 | 建议 |
|---|---|
是否推荐使用 private | ✅ 推荐用于封装敏感数据 |
是否允许修改 readonly 属性 | ❌ 否,只能在构造函数中赋值 |
| 如何避免类膨胀? | ✅ 使用组合代替继承 |
| 抽象类 vs 接口? | ✅ 抽象类适合共享逻辑,接口适合定义契约 |
是否推荐使用 override 关键字? | ✅ 推荐,增强代码可读性和安全性 |
十二、总结对比表:TypeScript 面向对象核心特性一览
| 特性 | 示例 | 说明 |
|---|---|---|
| 类定义 | class Person {} | 对象模板 |
| 构造函数 | constructor() | 初始化对象 |
| 访问修饰符 | public, private, protected | 控制访问权限 |
| 静态成员 | static PI = 3.14 | 属于类而非实例 |
| 只读属性 | readonly id: number | 不可变属性 |
| 抽象类 | abstract class Shape | 必须被继承实现 |
| 接口实现 | implements ILogger | 强制实现特定方法 |
| 继承与重写 | extends, override | 支持多态 |
| 多态调用 | 函数接受父类引用 | 根据实际类型执行不同方法 |
十三、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!