• 【TypeScript】类的基本使用


    TypeScript类的基本使用

    🍟类的介绍

    在早期的JavaScript开发中( ES5)我们需要通过函数和原型链来实现类和继承,从ES6开始,引入了class关键字,可以更加方便的定义和使用类。

    TypeScript作为JavaScript的超集,也是支持使用class关键字的,并且还可以对类的属性和方法等进行静态类型检测

    实际上在JavaScript的开发过程中,我们更加习惯于函数式编程

    比如React开发中,目前更多使用的函数组件以及结合Hook的开发模式;

    比如在Vue3开发中,目前也更加推崇使用 Composition API;

    但是在封装某些业务的时候,类具有更强大封装性,所以我们也需要掌握它们

    类的定义我们通常会使用class关键字:

    在面向对象的世界里,任何事物都可以使用类的结构来描述;

    类中包含特有的属性和方法;


    🍟类的定义

    例如我们使用class关键字来定义一个Person类 ;

    • 我们可以声明一些类的属性:在类的内部声明类的属性以及对应的类型

    类中如果类型没有声明,那么它们默认是any的;

    我们也可以给属性设置初始化值;

    在默认的strictPropertyInitialization模式下面我们的属性是必须初始化的

    class Person {
      name: string = ""
      age: number = 0
    }
    
    • 1
    • 2
    • 3
    • 4

    如果没有初始化,那么编译时就会报错;

    在这里插入图片描述

    如果我们在strictPropertyInitialization模式下确实不希望给属性初始化,可以使用 name!: string语法;

    class Person {
      name!: string
      age!: number
    }
    
    • 1
    • 2
    • 3
    • 4

    类可以有自己的构造函数constructor,当我们通过new关键字创建一个实例时,构造函数会被调用

    构造函数不需要返回任何值,默认返回当前创建出来的实例;

    我们也可以使用构造函数constructor对属性进行初始化

    class Person {
      name: string
      age: number
    
      constructor(name: string, age: number) {
        this.name = name
        this.age = age
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    类中可以有自己的函数,定义的函数称之为方法

    class Person {
      name: string
      age: number
    
      constructor(name: string, age: number) {
        this.name = name
        this.age = age
      }
    
      eating() {
        console.log("is eating")
      }
      running() {
        console.log("is running")
      }
    }
    
    // 测试
    const p = new Person("chenyq", 18)
    console.log(p.name)
    console.log(p.age)
    p.eating()
    p.running()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    🍟类的继承

    面向对象的其中一大特性就是继承,继承不仅仅可以减少我们的代码量,也是多态的使用前提

    我们使用extends关键字来实现继承,子类中使用super来访问父类

    我们来看一下Student类和Teacher类继承自Person类:

    Student类和Teacher类可以有自己的属性和方法,并且会继承Person的属性和方法;

    class Person {
      name: string = ""
      age: number = 0
    
      eating() {
        console.log("eating")
      }
    }
    
    class Student extends Person {
      score: number = 0
      
      studying() {
        console.log("studying")
      }
    }
    
    class Teacher extends Person {
      title: string = ""
      teaching() {
        console.log("teaching")
      }
    }
    
    // 测试
    const stu = new Student()
    stu.name = "chenyq"
    stu.age = 18
    console.log(stu.name)
    console.log(stu.age)
    stu.eating()
    stu.studying()
    
    const tea = new Teacher()
    tea.name = "kaisa"
    tea.age = 20
    console.log(tea.name)
    console.log(tea.age)
    tea.eating()
    tea.teaching()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    但是目前这种做法我们还需要在实例中对name, age属性赋值, 这种方式会很麻烦, 我们希望创建对象实例的时候就可以进行初始化

    在构造函数中,我们可以通过super()方法, 来调用父类的构造方法,对父类中的属性进行初始化;

    class Person {
      name: string
      age: number
    
      // 父类构造器
      constructor(name: string, age: number) {
        this.name = name
        this.age = age
      }
    
      eating() {
        console.log("eating")
      }
    }
    
    class Student extends Person {
      score: number = 0
    
      constructor(name: string, age: number, score: number) {
        // 调用父类构造器
        super(name, age)
        this.score = score
      }
      
      studying() {
        console.log("studying")
      }
    }
    
    // 测试
    const stu = new Student("chenyq", 18, 110)
    console.log(stu.name)
    console.log(stu.age)
    console.log(stu.score)
    stu.eating()
    stu.studying()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    目前我们调用的eating方法, 是由父类Person继承的, 当我们Student子类对父类方法不满意时, 我们可以重写

    class Student extends Person {
      score: number = 0
    
      constructor(name: string, age: number, score: number) {
        // 调用父类构造器
        super(name, age)
        this.score = score
      }
    
      // 重写父类方法
      eating() {
        console.log("student eating")
      }
      
      studying() {
        console.log("studying")
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    如果我们重写子类eating方法时, 又想让父类的eating方法也执行一次, 可以通过super调用

    class Student extends Person {
      score: number = 0
    
      constructor(name: string, age: number, score: number) {
        // 调用父类构造器
        super(name, age)
        this.score = score
      }
    
      // 重写父类方法
      eating() {
        // 子类中是由super, 再让父类的方法也执行一次
        super.eating()
        // 重写的部分
        console.log("student eating")
      }
      
      studying() {
        console.log("studying")
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    🍟类成员的修饰符

    在TypeScript中,类的属性和方法支持三种修饰符:public、 private、 protected

    • public修饰符: 是在任何地方可见、公有的属性或方法,默认编写的属性就是public的;

    例如下面代码中, 属性默认的修饰符是public, 因此可在任何地方访问

    class Person {
      name: string = ""
    }
    
    // 测试
    const p = new Person()
    // 可以在任何地方访问类中的额name属性
    p.name = "aaa"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • private修饰符: 是仅在同一类中可见、私有的属性或方法;

    private修饰的属性或方法, 只能在同一类中访问, 外部访问就会报错

    class Person {
      private name: string = "a"
    
      getName() {
        return this.name
      }
    }
    
    // 测试
    const p = new Person()
    // p.name // 外部无法访问
    console.log(p.getName())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • protected修饰符: 是仅在类自身及子类中可见、受保护的属性或方法;

    protected修饰符除自身类中可以访问之外, 子类中也可以访问, 外部同样无法访问到

    class Person {
      protected name: string = "a"
    }
    
    class Student extends Person {
      getName() {
        // 子类中也可以访问到protected
        return this.name
      }
    }
    
    // 测试
    const stu = new Student()
    console.log(stu.getName())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    🍟只读属性

    readonly准确的说也是一个修饰符, 使用readonly修饰符修饰的属性是一个只读属性

    如果有一个属性我们不希望外界可以任意的修改,只希望确定值后直接使用,那么可以使用readonly修饰符

    class Person {
      readonly name: string = "aaa"
    }
    
    // 测试
    const p = new Person()
    console.log(p.name)
    // p.name = "bbb" // 只能读, 不能修改
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    但是只读属性是可以在constructor构造器中赋值的, 赋值之后同样不可修改, 演示如下

    class Person {
      readonly name: string
      
      constructor(name: string) {
        this.name = name
      }
    }
    
    // 测试
    const p = new Person("abc")
    console.log(p.name)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    🍟getters/setters

    在前面一些私有属性我们是不能直接访问的,或者某些属性我们想要监听它的获取(getter)和设置(setter)的过程, 这个时候我们可以使用访问器

    访问器的定义是类似一个函数的形式, 而调用又和一般函数不一样, 类似于属性的方式

    class Person {
      private _name: string
      constructor(name: string) {
        this._name = name
      }
    
      // 访问器 setter/getter定义方式
      set name(newName) {
        this._name = newName
      }
    
      get name() {
        return this._name
      }
    }
    
    // 测试
    const p = new Person("abc")
    // 访问器的访问方式
    p.name = "aaa"
    console.log(p.name)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    🍟类的静态成员

    面我们在类中定义成员的属性和方法都属于对象实例的, 但是在开发中, 我们有时候也需要定义类级别的成员和方法(也就是类属性、类方法)

    在TypeScript中通过关键字static来定义

    class Student {
      // 定义类的属性
      static time: string = "20:00"
    
      // 定义类方法
      static studying() {
        console.log("去上课学习")
      }
    }
    
    // 测试
    console.log(Student.time)
    Student.studying()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    RestTemplate工具类
    Docker 容器监控 - Weave Scope
    源码分析基础
    【Linux集群教程】04 集群存储概述 & 存储分类-存储技术
    通过隧道功能在安全标准较高的情况下访问Linux
    JSP webshell免杀——JSP的基础
    New PMC 田原: 开源给了我一个接触非业务系统的机会
    林沛满---一个面试建议
    一次性彻底解决 Web 工程中文乱码问题
    【C++】最通俗的多态、虚表、虚指针讲解
  • 原文地址:https://blog.csdn.net/m0_71485750/article/details/126333091