• TypeScript 第三章:类 class



    类的定义

    下面是使用 TS 约束属性并实例化对象

    class User {
        name: string
        age: number
        constructor(name: string, age: number) {
            this.name = name
            this.age = age
        }
        getInfo = (): string => {
            return `${this.name}的年龄是${this.age}`
        }
    }
    
    const hj = new User('hj', 19)
    const hk = new User('hk', 20)
    console.log(hj.getInfo()); // hj的年龄是19
    console.log(hk.getInfo()); // hk的年龄是20
    
    const users: User[] = [hj, hk]
    console.log(users);
    // [
    //     User { getInfo: [Function (anonymous)], name: '张三', age: 19 },
    //     User { getInfo: [Function (anonymous)], name: 'hk', age: 20 }
    // ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    通过约束数组的类型为User,使其成员只能是 User 类型对象

    ...
    const users: User[] = [hj, hk]
    console.log(users);
    ...
    
    • 1
    • 2
    • 3
    • 4

    修饰符

    public

    class User {
        public name: string
        public age: number
        constructor(name: string, age: number) {
            this.name = name
            this.age = age
        }
        public getInfo = (): string => {
            return `${this.name}的年龄是${this.age}`
        }
    }
    
    const hj = new User('hj', 19)
    const hk = new User('hk', 20)
    hj.name = '张三'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    protected

    protected 修饰符指受保护的,只允许在父类与子类使用,不允许在类的外部使用

    class User {
        protected name: string
        public age: number
        constructor(name: string, age: number) {
            this.name = name
            this.age = age
        }
        public getInfo = (): string => {
            return `${this.name}的年龄是${this.age}` // 内部是可以访问 protected 的
        }
    }
    
    const hj = new User('hj', 19)
    hj.name = '张三' // 属性“name”受保护,只能在类“User”及其子类中访问
    console.log(hj.getInfo()); // 张三的年龄是19
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    private

    private 修饰符指私有的,不允许在子类与类的外部使用

    • 子类不能访问父类的 private 属性或方法
    class Person {
        protected name: string
        private age: number
        protected info = (): string => {
            return `${this.name}的年龄是${this.age}`
        }
    }
    
    class User extends Person {
        constructor(name: string, age: number) {
            super()
            this.name = name
            this.age = age // 子类不能访问父类的 private 属性或方法
        }
        public getInfo = (): string => {
            return this.info()
        }
    }
    
    const hj = new User('hj', 19)
    console.log(hj.getInfo()); // hj的年龄是19
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    • 父类声明 private 属性或方法子类不允许覆盖
    class Person {
        protected name: string
        private age: number
        private getInfo = (): string => {
            return `${this.name}的年龄是${this.age}`
        }
    }
    
    // 类“User”错误扩展基类“Person”。
    // 属性“getInfo”在类型“Person”中是私有属性,但在类型“User”中不是
    class User extends Person {
        constructor(name: string, age: number) {
            super()
            this.name = name
        }
        public getInfo = (): string => {
            return `姓名:${this.name}`
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    • 修饰符 子类访问或更改父类属性或方法是有限制的
      • 父类的 private 不允许只类修改
      • 父类的 protected 子类可以修改为 protected 或 public
      • 父类的 public 子类只能设置为 public
    class Person {
        protected name: string
        private age: number
    }
    
    // 类“User”错误扩展基类“Person”。
    class User extends Person {
        private name: string // 属性“name”在类型“User”中是私有属性,但在类型“Person”中不是
        constructor(name: string, age: number) {
            super()
            this.name = name
        }
        public getInfo = (): string => {
            return `姓名:${this.name}`
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    readonly

    readonly 将属性定义为只读,不允许在类的内部与外部进行修改

    类似于其他语言的 const 关键字

    class User {
        protected name: string
        private age: number
        readonly sex: string
        constructor(name: string, age: number, sex: string) {
            this.name = name
            this.sex = sex
        }
        public getInfo = (): string => {
            return `姓名:${this.name},性别${this.sex}`
        }
    }
    
    const hj = new User('hj', 19, '男')
    console.log(hj.sex); // 男
    hj.sex = '保密' // 无法分配到 "sex" ,因为它是只读属性
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    constructor

    构造函数是初始化实例参数使用的,在 TS 中有些细节与其他程序不同

    我们可以在构造函数 constructor 中定义属性,这样就不用在类中声明属性了,可以简化代码量

    必须要在属性前加上 public、private、readonly 等修饰符才有效

    class User {
        constructor(public name: string) {}
        getInfo = () => {
            return this.name
        }
    }
    const hj = new User('hj')
    console.log(hj.getInfo()); // hj
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    static

    static 用于定义静态属性或方法,属性或方法是属于构造函数的

    静态属性是属于构造函数的,不是对象独有的,所以是所有对象都可以共享的


    语法介绍

    下面是 static 使用的语法

    class User {
        static sex: string = '保密'
    
        static getUserInfo() {
            return '性别是' + User.sex
        }
    }
    const hj = new User()
    console.log(hj.getUserInfo()); // jsError 属性“getUserInfo”在类型“User”上不存在
    console.log(User.getUserInfo()); // 性别是保密
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    单例模式

    当把 construct 定义为非 public 修饰符后,就不能通过这个类实例化对象了。

    class User {
        protected constructor() {
    
        }
    }
    
    const hj = new User(); // 类“User”的构造函数是受保护的,仅可在类声明中访问
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    我们可以利用这个特性再结合 static 即可实现单例模式,即只实例化一个对象

    class User {
        static instance: User | null = null;
        protected constructor() { }
    
        public static make(): User {
            if (User.instance == null) User.instance = new User;
    
            return User.instance;
        }
    }
    
    const hj = User.make();
    console.log(hj);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    get/set

    使用 get 与 set 访问器可以动态设置和获取属性,类似于 vue 或 laravel 中的计算属性

    class User {
        constructor(public _name: string) {}
        
        public get name () {
            return this._name
        }
    
        public set name (value: string) {
            this._name = value
        }
    }
    
    const hj = new User('hj')
    
    console.log(hj.name); // hj
    hj.name = 'hk'
    console.log(hj.name); // hk
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    abstract

    抽象类定义使用 abstract 关键字,抽象类除了具有普通类的功能外,还可以定义抽象方法

    • 抽象类可以不包含抽象方法,但抽象方法必须存在于抽象类中
    • 抽象方法是对方法的定义,子类必须实现这个方法
    • 抽象类不可以直接使用,只能被继承
    • 抽象类类似于类的模板,实现规范的代码定义

    下例中的子类都有 move 方法,我们可以在抽象方法中对其进行规范定义

    class Animation {
        protected getPos() {
            return { x: 100, y: 300 }
        }
    }
    
    class Tank extends Animation {
        public move(): void {}
    }
    
    class Player extends Animation {
        public move(): void {}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    • 抽象方法只能定义,不能实现,即没有函数体
    • 子类必须实现抽象方法
    abstract class Animation {
        abstract move(): void
        protected getPos() {
            return { x: 100, y: 300 }
        }
    }
    
    // 非抽象类“Tank”不会实现继承自“Animation”类的抽象成员“move”
    class Tank extends Animation {
        // public move(): void {}
    }
    
    class Player extends Animation {
        public move(): void {}
    }
    
    const tank = new Tank()
    const player = new Player()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    • 子类必须实现抽象类定义的抽象属性
    abstract class Animation {
        abstract move(): void
        abstract name: string
        protected getPos() {
            return { x: 100, y: 300 }
        }
    }
    
    // 非抽象类“Tank”不会实现继承自“Animation”类的抽象成员“name”
    class Tank extends Animation {
        // public name = '敌方'
        public move(): void {}
    }
    
    class Player extends Animation {
        public name = '玩家'
        public move(): void {}
    }
    
    const tank = new Tank()
    const player = new Player()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    抽象类不能被直接使用,只能被继承

    abstract class Animation {
        abstract move(): void
        abstract name: string
        protected getPos() {
            return { x: 100, y: 300 }
        }
    }
    
    const animation = new Animation() // 无法创建抽象类的实例
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    浏览器中的原生base64方法
    TMS Diagram Studio 一组组件Crack版
    【Vue】之Vuex的入门使用,取值,修改值,同异步请求处理---保姆级别教学
    自然语言处理应用(二):自然语言推断
    Golang context包的源码分析
    JVM—Class类文件结构详解
    测试面试 | 某 BAT 大厂测试开发面试真题与重点解析
    渗透测试CTF-流量分析
    【BOOST C++容器专题03】【06】Boost.Heap
    JavaScript_与html结合方式
  • 原文地址:https://blog.csdn.net/qq_41887214/article/details/125534302