TypeScript 从入门到进阶之基础篇(九) Class类篇

发布时间:2024年01月08日

请添加图片描述

系列文章目录

TypeScript 从入门到进阶系列

  1. TypeScript 从入门到进阶之基础篇(一) ts基础类型篇
  2. TypeScript 从入门到进阶之基础篇(二) ts进阶类型篇
  3. TypeScript 从入门到进阶之基础篇(三) 元组类型篇
  4. TypeScript 从入门到进阶之基础篇(四) symbol类型篇
  5. TypeScript 从入门到进阶之基础篇(五) 枚举类型篇
  6. TypeScript 从入门到进阶之基础篇(六) 类型(断言 、推论、别名)| 联合类型 | 交叉类型 篇
  7. TypeScript 从入门到进阶之基础篇(七)泛型篇
  8. TypeScript 从入门到进阶之基础篇(八)函数篇
    持续更新中…


前言

在JavaScript中class(类)是一种组织代码的方式,它允许我们创建对象和对象的行为。它是一种面向对象编程(OOP)的概念,在ES6中被引入,通过class关键字,可以定义类。使用class关键字可以定义类,通过类可以创建多个实例对象。本章将讲解如何在TypeScript 中使用class(类)。


一、class类的基本使用

定义类的语法与JavaScript类似,使用class关键字来定义一个类。类可以包含属性、方法和构造函数等。

注意:在TypeScript是不允许直接在constructor 定义变量的 需要先在constructor的上面进行声明

例如,下面是一个简单的示例,演示了如何在TypeScript中定义一个类:

class Person {
	//先进行声明
  name: string;
  age: number;
	//才能在constructor 中使用
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  sayHello() {
    console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
  }
}

let person = new Person("John", 25);
person.sayHello();

在上面的例子中,我们定义了一个名为Person的类,它有两个属性nameage,一个构造函数和一个sayHello方法。构造函数用于创建类的实例,并接受nameage作为参数。

我们可以使用new关键字来创建一个Person对象,并调用sayHello方法来输出欢迎消息。

二、class类中的修饰符

类成员(属性和方法)可以使用以下修饰符来定义其访问权限:

  1. public: 默认修饰符,表示成员在类内部和外部都可以访问。
  2. private: 表示成员只能在类内部访问,外部无法访问。
  3. protected: 表示成员可以在类内部和该类的子类中访问,外部无法访问。
  4. readonly: 表示成员只能在初始化时或构造函数中赋值,并且不能被修改。
  5. static: 表示成员属于类本身,而不是类的实例。可以在类内部和类外部直接访问,无需实例化。

例如,以下代码示例演示了如何使用修饰符:

class Person {
  public name: string; // 公有属性,默认修饰符
  private age: number; // 私有属性
  protected gender: string; // 受保护属性
  readonly id: string; // 只读属性
  static count: number; // 静态属性

  constructor(name: string, age: number, gender: string, id: string) {
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.id = id;
    Person.count++;
  }

  public sayHello() {
    console.log(`Hello, my name is ${this.name}.`);
  }

  private getAge() {
    return this.age;
  }

  protected getGender() {
    return this.gender;
  }

  static getCount() {
    return Person.count;
  }
}

const person = new Person('John', 25, 'male', '1234567890');
console.log(person.name); // 可访问,输出 'John'
// console.log(person.age); // 私有属性,无法访问
// console.log(person.gender); // 受保护属性,无法访问
console.log(person.id); // 只读属性,可访问,输出 '1234567890'
person.sayHello(); // 可调用,输出 'Hello, my name is John.'
// person.getAge(); // 私有方法,无法调用
// person.getGender(); // 受保护方法,无法调用
console.log(Person.count); // 静态属性,可直接访问,输出当前实例数

这是一个使用各种修饰符定义类成员的例子,你可以根据自己的需求选择适当的修饰符来限制成员的访问权限。

三、class类中存取器的使用

存取器(accessor)是一种特殊的属性,用于对类的属性进行读取和写入操作。存取器由get和set关键字定义,分别用于获取和设置属性的值。

下面是一个使用存取器的示例:

class Person {
  private _name: string;

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

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

let person = new Person();
person.name = "Alice";
console.log(person.name); // Output: Alice

在上面的例子中,Person类具有一个私有属性_name和一个公共的存取器name。存取器name的get方法返回_name的值,set方法设置_name的值。通过使用存取器,我们可以在外部像访问属性一样获取和设置_name的值。

另外,存取器可以有只读的属性。只读属性只有get方法,没有set方法,一旦设置了初始值后就不能再修改。

class Person {
  private readonly _name: string;

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

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

let person = new Person("Alice");
console.log(person.name); // Output: Alice
person.name = "Bob"; // Error: Cannot assign to 'name' because it is a read-only property

在上面的例子中,Person类的_name属性是只读的,只能通过构造函数初始化,并且不能修改其值。通过使用只读属性,我们可以限制属性的修改,提高代码的可靠性和安全性。

四、用接口定义类

可以使用接口来定义类。可以在接口中定义类的属性和方法,并且类需要遵循接口的定义。

下面是一个示例:

interface Animal {
  name: string;
  age: number;
  sound(): void;
}

class Dog implements Animal {
  name: string;
  age: number;

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

  sound(): void {
    console.log("Woof!");
  }
}

let myDog: Animal = new Dog("Max", 5);
myDog.sound(); // 输出 "Woof!"

在上面的例子中,定义了一个Animal接口,它包含了name、age和sound方法。然后创建了一个Dog类,它实现了Animal接口。最后,创建了一个myDog对象,它是一个Animal类型的变量,可以调用sound方法。

通过使用接口来定义类,可以使代码更加清晰和易于维护,同时也可以提供更好的类型检查和类型推断。

五、类的继承

类之间可以通过继承来建立父子关系。一个类可以继承另一个类的属性和方法,并且可以添加自己的属性和方法。类的继承使用 extends
关键字。

下面是一个示例,展示了一个父类 Animal 和一个子类 Cat 的继承关系:

class Animal {
  name: string;

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

  makeSound() {
    console.log('Animal is making a sound.');
  }
}

class Cat extends Animal {
  meow() {
    console.log('Cat is meowing.');
  }
}

const myCat = new Cat('Tom');
console.log(myCat.name); // 输出 "Tom"
myCat.makeSound(); // 输出 "Animal is making a sound."
myCat.meow(); // 输出 "Cat is meowing."

在上面的例子中,Cat 类继承了 Animal 类,因此它拥有了 name 属性和 makeSound() 方法。同时,它还添加了自己的方法 meow()

注意,当子类继承父类时,子类的构造函数中必须调用 super() 方法,以调用父类的构造函数,并传递必要的参数。在上面的例子中,Cat 类的构造函数调用了 super(name),以调用 Animal 类的构造函数。

此外,子类还可以重写父类的方法。在子类中,可以使用 super 关键字来调用父类的方法。例如,在上面的例子中,Cat 类的 makeSound() 方法重写了父类的方法,但在方法体内部通过 super.makeSound() 来调用父类的方法。

六、抽象类的使用

可以使用抽象类来定义一个抽象的基类,它不能被直接实例化,只能被继承。抽象类可以包含抽象方法和非抽象方法。

下面是一个使用抽象类的示例:

abstract class Animal {
  protected name: string;

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

  abstract makeSound(): void;

  move(distance: number): void {
    console.log(`${this.name} moved ${distance} meters.`);
  }
}

class Cat extends Animal {
  makeSound(): void {
    console.log(`${this.name} makes sound: Meow!`);
  }
}

let myCat: Cat = new Cat("Tom");
myCat.makeSound(); // 输出 "Tom makes sound: Meow!"
myCat.move(10); // 输出 "Tom moved 10 meters."

在上述代码中,Animal 类是一个抽象类,它有一个抽象方法 makeSound 和一个非抽象方法 moveCat 类继承自 Animal 类,并实现了 makeSound 方法。我们创建一个 Cat 类的实例 myCat,并调用它的方法和非抽象方法。


总结

总结起来,使用 TypeScript类可以方便地定义和组织代码,提供了面向对象编程的特性,如封装、继承和多态。同时,通过类型检查,可以减少一些常见的错误,并提供更好的代码智能提示。

文章来源:https://blog.csdn.net/weixin_49014702/article/details/135461797
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。