TypeScript_3_typescript类与接口的使用

TypeScript_3_typescript类与接口的使用

TypeScript类的使用

认识类的使用

  • 在早期的JavaScript开发中(ES5)我们需要通过函数和原型链来实现类和继承,从ES6开始,引入了class关键字,可以更加方便的定义和使用类。
  • TypeScript作为JavaScript的超集,也是支持使用class关键字的,并且还可以对类的属性和方法等进行静态类型检测。
  • 实际上在JavaScript的开发过程中,我们更加习惯于函数式编程:
    • 比如React开发中,目前更多使用的函数组件以及结合Hook的开发模式;
    • 比如在Vue3开发中,目前也更加推崇使用CompositionAPI;
  • 但是在封装某些业务的时候,类具有更强大封装性,所以我们也需要掌握它们。
  • 类的定义我们通常会使用class关键字:
    • 在面向对象的世界里,任何事物都可以使用类的结构来描述;
    • 类中包含特有的属性和方法;

类的定义

  • 我们来定义一个Person类:

    在这里插入图片描述

  • 使用class关键字来定义一个类;

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

    • 如果类型没有声明,那么它们默认是any的;
    • 我们也可以给属性设置初始化值;
    • 在默认的strictPropertyInitialization模式下面我们的属性是必须初始化的,如果没有初始化,那么编译时就会报错;
      • 如果我们在strictPropertyInitialization模式下确实不希望给属性初始化,可以使用name!:string语法;
  • 类可以有自己的构造函数constructor,当我们通过new关键字创建一个实例时,构造函数会被调用;

    • 构造函数不需要返回任何值,默认返回当前创建出来的实例;
  • 类中可以有自己的函数,定义的函数称之为方法;

类的继承

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

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

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

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

    • 在构造函数中,我们可以通过super来调用父类的构造方法,对父类中的属性进行初始化;
      在这里插入图片描述
      在这里插入图片描述

类的多态

  • 基于继承和接口实现

    class Animal {
      action() {
        console.log("animal action")
      }
    }
    
    class Dog extends Animal {
      action() {
        console.log("dog running!!!")
      }
    }
    
    class Fish extends Animal {
      action() {
        console.log("fish swimming")
      }
    }
    
    class Person extends Animal {
    
    }
    
    // animal: dog/fish
    // 多态的目的是为了写出更加具备通用性的代码
    function makeActions(animals: Animal[]) {
      animals.forEach(animal => {
        animal.action()
      })
    }
    
    makeActions([new Dog(), new Fish(), new Person()])
    
    

类的成员修饰符

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

    • public修饰的是在任何地方可见、公有的属性或方法,默认编写的属性就是public的;
    • private修饰的是仅在同一类中可见、私有的属性或方法;
    • protected修饰的是仅在类自身及子类中可见、受保护的属性或方法;
  • public是默认的修饰符,也是可以直接访问的,我们这里来演示一下protected和private。
    在这里插入图片描述
    在这里插入图片描述

只读属性readonly

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

    在这里插入图片描述

getters/setters

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

静态成员

  • 前面我们在类中定义的成员和方法都属于对象级别的,在开发中,我们有时候也需要定义类级别的成员和方法。

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

    在这里插入图片描述

抽象类abstract

  • 我们知道,继承是多态使用的前提。
    • 所以在定义很多通用的调用接口时,我们通常会让调用者传入父类,通过多态来实现更加灵活的调用方式。
    • 但是,父类本身可能并不需要对某些方法进行具体的实现,所以父类中定义的方法,,我们可以定义为抽象方法。
  • 什么是抽象方法? 在TypeScript中没有具体实现的方法(没有方法体),就是抽象方法。
    • 抽象方法,必须存在于抽象类中;
    • 抽象类是使用abstract声明的类;
  • 抽象类有如下的特点:
    • 抽象类是不能被实例的话(也就是不能通过new创建)
    • 抽象方法必须被子类实现,否则该类必须是一个抽象类;

抽象类演练

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

类的类型

  • 类本身也是可以作为一种数据类型的:

    在这里插入图片描述

TypeScript接口的使用

接口的声明

  • 在前面我们通过type可以用来声明一个对象类型:

    在这里插入图片描述

  • 对象的另外一种声明方式就是通过接口来声明:

    在这里插入图片描述

  • 他们在使用上的区别,我们后续再来说明。

  • 接下来我们继续学习一下接口的其他特性。

可选属性

  • 接口中我们也可以定义可选属性:

    在这里插入图片描述

只读属性

  • 接口中也可以定义只读属性:

    • 这样就意味着我们再初始化之后,这个值是不可以被修改的;

      在这里插入图片描述

      在这里插入图片描述

索引类型

  • 前面我们使用interface来定义对象类型,这个时候其中的属性名、类型、方法都是确定的,但是有时候我们会遇到类似下面的对象:

    在这里插入图片描述

    在这里插入图片描述

函数类型

  • 前面我们都是通过interface来定义对象中普通的属性和方法的,实际上它也可以用来定义函数类型:

    在这里插入图片描述

  • 当然,除非特别的情况,还是推荐大家使用类型别名来定义函数:

    在这里插入图片描述

接口继承

  • 接口和类一样是可以进行继承的,也是使用extends关键字:

    • 并且我们会发现,接口是支持多继承的(类不支持多继承)

      在这里插入图片描述

      在这里插入图片描述

接口的实现

  • 接口定义后,也是可以被类实现的:

    • 如果被一个类实现,那么在之后需要传入接口的地方,都可以将这个类传入;

    • 这就是面向接口开发;

      在这里插入图片描述

      在这里插入图片描述

  • 交叉类型

  • 前面我们学习了联合类型:

    • 联合类型表示多个类型中一个即可

      在这里插入图片描述

  • 还有另外一种类型合并,就是交叉类型(Intersection Types):

    • 交叉类似表示需要满足多个类型的条件;
    • 交叉类型使用 & 符号;
  • 我们来看下面的交叉类型:

    • 表达的含义是number和string要同时满足;

    • 但是有同时满足是一个number又是一个string的值吗?其实是没有的,所以MyType其实是一个never类型;

      在这里插入图片描述

交叉类型的应用

  • 所以,在开发中,我们进行交叉时,通常是对对象类型进行交叉的:

    在这里插入图片描述

interface和type区别

  • 我们会发现interface和type都可以用来定义对象类型,那么在开发中定义对象类型时,到底选择哪一个呢?
    • 如果是定义非对象类型,通常推荐使用type,比如Direction、Alignment、一些Function;
  • 如果是定义对象类型,那么他们是有区别的:
    • interface 可以重复的对某个接口来定义属性和方法;
    • 而type定义的是别名,别名是不能重复的;

在这里插入图片描述
在这里插入图片描述

字面量赋值

  • 我们来看下面的代码:
    在这里插入图片描述
    在这里插入图片描述

  • 这是因为TypeScript在字面量直接赋值的过程中,为了进行类型推导会进行严格的类型限制。

    • 但是之后如果我们是将一个 变量标识符 赋值给其他的变量时,会进行freshness擦除操作。

TypeScript枚举类型

  • 枚举类型是为数不多的TypeScript特性有的特性之一:

    • 枚举其实就是将一组可能出现的值,一个个列举出来,定义在一个类型中,这个类型就是枚举类型;

    • 枚举允许开发者定义一组命名常量,常量可以是数字、字符串类型;

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HiMvnLle-1646557024976)(img/image-20220305193519482.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lLkWQ8wP-1646557024977)(img/image-20220305193526954.png)]

枚举类型的值

  • 枚举类型默认是有值的,比如上面的枚举,默认值是这样的:

  • 当然,我们也可以给枚举其他值:

    • 这个时候会从100进行递增;
  • 我们也可以给他们赋值其他的类型:

    在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值