类的定义与实例化

在面向对象编程中,类是对现实世界事物的抽象描述。例如,我们可以将“用户”这一概念抽象为包含属性(如姓名、年龄)和行为(如打招呼)的类结构,从而在代码中构建具有统一特征的对象模型。

类的定义:从抽象到具体

以“用户类”(User)为例,一个完整的类定义包含属性声明构造函数实例方法三个核心部分:

typescript
复制代码
class User {
  // 属性声明:定义类的特征
  name: string; 
  age: number;

  // 构造函数:初始化实例属性
  constructor(name: string, age: number) {
    this.name = name; // 使用this访问实例属性
    this.age = age;
  }

  // 实例方法:定义类的行为
  greet(): string {
    return `Hello, ${this.name}`; // 通过this调用实例属性
  }
}
  • 属性声明name: stringage: number 明确了类实例将包含的特征及其类型,为TypeScript的类型检查提供依据。
  • 构造函数:通过 constructor 关键字定义,在实例创建时自动执行,用于初始化对象的属性值。上述代码中,构造函数接收 nameage 参数,并通过 this 关键字将参数值赋给实例属性。
  • 实例方法greet() 是类的行为定义,通过 this 访问实例属性,实现对对象数据的操作或返回计算结果。

实例化:创建类的具体对象

定义类后,需通过 new 关键字创建实例,才能使用类的属性和方法。例如,创建名为“Alice”、年龄25岁的用户实例:

typescript
复制代码
const user = new User("Alice", 25); 
console.log(user.name); // 输出:Alice(访问实例属性)
console.log(user.greet()); // 输出:Hello, Alice(调用实例方法)

``
new 关键字的作用

  1. 创建一个空对象({}),并将其作为实例;
  2. 将实例的 this 绑定到该对象;
  3. 执行构造函数,初始化实例属性;
  4. 返回初始化后的实例对象。

访问修饰符:控制属性访问权限

TypeScript提供三种访问修饰符,用于实现封装特性,控制类属性的访问范围:

修饰符 访问范围 默认值
public 类内部、外部、子类均可访问
private 仅类内部可访问
protected 类内部及子类可访问

1. public(默认)
未显式声明修饰符时,属性默认为 public,可在类外部直接访问:

typescript
复制代码
class User {
  public name: string; // 等同于 `name: string`
  // ...
}
const user = new User("Alice", 25);
console.log(user.name); // 正常输出:Alice(外部可访问)

2. private(私有)
使用 private 修饰的属性仅能在类内部访问,外部访问将触发TypeScript编译错误:

typescript
复制代码
class User {
  private age: number; // 私有属性
  constructor(name: string, age: number) {
    this.age = age;
  }
  getAge(): number {
    return this.age; // 类内部可访问
  }
}
const user = new User("Alice", 25);
console.log(user.age); // ❌ 错误:属性“age”为私有属性,只能在类“User”中访问
console.log(user.getAge()); // ✅ 正常输出:25(通过类方法间接访问)

3. protected(受保护)
protected 修饰的属性允许类内部及子类访问,但外部仍不可访问:

typescript
复制代码
class User {
  protected id: number;
  constructor(id: number) {
    this.id = id;
  }
}
class AdminUser extends User {
  getAdminId(): number {
    return this.id; // 子类可访问protected属性
  }
}
const admin = new AdminUser(1001);
console.log(admin.id); // ❌ 错误:属性“id”受保护,只能在类“User”及其子类中访问

``
封装的核心价值:通过 privateprotected 隐藏内部实现细节,仅暴露必要的操作接口(如 getAge()),避免外部误修改导致的数据不一致问题。

扩展练习:实现购物车类

需求:设计一个 ShoppingCart 类,包含以下功能:

  • private 修饰内部商品列表,禁止外部直接修改;
  • 提供 addItem(item) 方法添加商品(商品格式:{ id: number; name: string; price: number });
  • 提供 calculateTotal() 方法计算商品总价。

参考实现

typescript
复制代码
class ShoppingCart {
  // 私有商品列表,外部无法直接访问或修改
  private items: { id: number; name: string; price: number }[] = [];

  // 添加商品
  addItem(item: { id: number; name: string; price: number }): void {
    this.items.push(item);
  }

  // 计算总价
  calculateTotal(): number {
    return this.items.reduce((sum, item) => sum + item.price, 0);
  }
}

// 使用示例
const cart = new ShoppingCart();
cart.addItem({ id: 1, name: "笔记本", price: 4999 });
cart.addItem({ id: 2, name: "鼠标", price: 199 });
console.log(cart.calculateTotal()); // 输出:5198
console.log(cart.items); // ❌ 错误:属性“items”为私有属性,只能在类“ShoppingCart”中访问

通过 private items 确保商品列表仅能通过 addItem 方法修改,避免外部直接操作数组导致的数据错误,体现了封装的设计思想。