TypeScript:9、Class 与封装

Class 与封装

面向对象编程会把程序中的数据和功能组织到对象中。TypeScript 通过 class 定义对象模型,通过访问修饰符控制数据的访问范围。

一、类和对象的关系

  • 类是对象的模型或模板。
  • 对象是根据类创建出来的实例。
  • 属性用于保存数据。
  • 方法用于描述对象的行为。

例如,可以使用 Person 类创建多个不同的人对象。

二、定义一个类

class Person {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  sayHello(): void {
    console.log('大家好,我是' + this.name);
  }
}

通过 new 创建实例:

const person = new Person('孙悟空', 18);
person.sayHello();

三、构造函数和 this

构造函数使用 constructor 声明,在创建实例时自动执行。this 表示当前实例对象。

class User {
  username: string;

  constructor(username: string) {
    this.username = username;
  }
}

构造函数参数也可以直接声明为属性,这种写法叫参数属性:

class Product {
  constructor(
    public name: string,
    public price: number
  ) {}
}

const product = new Product('键盘', 299);

四、访问修饰符

TypeScript 中常见的访问修饰符有三个:

修饰符类内部子类类外部对象
public可以访问可以访问可以访问
protected可以访问可以访问不能访问
private可以访问不能访问不能访问

1. public

public 是默认修饰符,省略修饰符时也表示公开成员:

class Person {
  public name: string;

  constructor(name: string) {
    this.name = name;
  }
}

const person = new Person('孙悟空');
person.name = '猪八戒';

2. protected

protected 成员只能在当前类和子类中访问:

class Person {
  protected name: string;

  constructor(name: string) {
    this.name = name;
  }
}

class Employee extends Person {
  printName(): void {
    console.log(this.name);
  }
}

const employee = new Employee('唐僧');
employee.printName();

// 编译错误:类外部不能直接访问 protected 成员
// employee.name;

3. private

private 成员只能在当前类内部访问:

class Account {
  private balance: number;

  constructor(balance: number) {
    this.balance = balance;
  }

  getBalance(): number {
    return this.balance;
  }
}

const account = new Account(1000);
console.log(account.getBalance());

// 编译错误:类外部不能直接访问 private 成员
// account.balance;

五、readonly 只读属性

使用 readonly 可以限制属性不能被重新赋值:

class User {
  readonly id: number;

  constructor(id: number) {
    this.id = id;
  }
}

const user = new User(1001);

// 编译错误:id 是只读属性
// user.id = 1002;

readonly 属性通常可以在声明时或构造函数中初始化,之后不能再次修改。

六、属性存取器 getter 和 setter

当属性需要被保护,但又希望对外提供读取或修改入口时,可以使用属性存取器。

  • get 用于读取属性。
  • set 用于修改属性。
class Person {
  private _name: string;

  constructor(name: string) {
    this._name = name;
  }

  get name(): string {
    return this._name;
  }

  set name(name: string) {
    if (name.trim() !== '') {
      this._name = name;
    }
  }
}

const person = new Person('孙悟空');
console.log(person.name);
person.name = '猪八戒';

调用存取器时不需要写括号,使用方式和普通属性类似。

七、静态属性和静态方法

使用 static 声明的成员属于类本身,不属于某个实例。使用静态成员时不需要创建对象。

class Tools {
  static PI: number = 3.1415926;

  static sum(num1: number, num2: number): number {
    return num1 + num2;
  }
}

console.log(Tools.PI);
console.log(Tools.sum(123, 456));

实例成员通过对象访问,静态成员通过类名访问:

实例成员 → person.name
静态成员 → Tools.PI

八、封装的意义

封装就是把数据和操作数据的方法放在一起,并限制外部直接修改内部状态。

例如账户余额不应该被随意修改,可以通过方法控制业务规则:

class BankAccount {
  private balance: number;

  constructor(balance: number) {
    this.balance = balance;
  }

  deposit(amount: number): void {
    if (amount > 0) {
      this.balance += amount;
    }
  }

  getBalance(): number {
    return this.balance;
  }
}

九、常见问题

1. 把 private 当成运行时绝对安全

private 主要由 TypeScript 在编译阶段检查。它的作用是约束代码访问方式,而不是替代真正的安全机制。

2. 直接公开所有属性

如果属性有合法范围或业务规则,建议使用 private 配合方法或存取器进行控制。

3. 在静态方法中直接访问实例属性

静态方法没有具体实例,不能直接访问实例成员:

class Example {
  name: string = 'demo';

  static print(): void {
    // 不能直接访问 this.name
    // console.log(this.name);
  }
}

十、本章小结

  • class 用于定义对象模型。
  • constructor 用于初始化实例。
  • publicprotectedprivate 用于控制访问范围。
  • readonly 可以保护只读数据。
  • getset 可以安全地读取和修改私有属性。
  • static 成员属于类本身,不需要创建实例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sunly_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值