「极速上手TypeScript」TypeScript进阶“接口”

一、接口
1. 接口的定义

我们在其他语言中如:c++, java, python等语言接口我们会花大量时间去学习,但在TS中,我们不需要花费太多的时间在接口上,他没有上述语言中接口这么难理解和使用,大家在学习TS中的接口时可以想着"此接口非彼接口",简单的来说TS中的类是用来描述一个类型

下面来看看在代码中的定义吧:

定义接口需要使用关键字:interface

//定义接口类型
interface Employee {
  name: string,
  salary: number
}

这就是一个简单的接口

下面我们来看看如何来使用这个接口吧!

const em1:Employee =  {
    name:'jhon',
    salary: 123,
}

const em2: Employee = {
    name: 'ice_moss',
    salary: 8000,
}

console.log(em2, em1)

输出结果:

{
  "name": "ice_moss",
  "salary": 8000,
},  {
  "name": "jhon",
  "salary": 12000
} 

我们定义了一个接口Employee,接着定义了变量em1和em2他们的类型是Employee,使用em1和em2实现了Employee的属性和方法,我们称em1和em2实现了Employee的接口

2. 接口的语法

上面的实例中我们只在接口中描述了属性,下面我们将属性和方法一起实现:

//定义接口类型
interface Employee {
    name: string   
    salary: number
    bonus?: number
    getIncom():number  
}

const em1:Employee =  {
    name:'jhon',
    salary: 12000,
    bonus: 2000,
    getIncom(){
        return this.salary
    }
}

const em2: Employee = {
    name: 'ice_moss',
    salary: 8000,
    bonus: 3000,
    getIncom(){
        return this.salary + (this.bonus || 0)
    }
}
3. 接口的高级用法
3. 1可选参数串联
interface Employee {
  name?:{     //可选参数
    first?: string  //可选参数
    last: string
  }
  salary: number
  bonus?: number
}

//寻找可选参数
function hasBadName(e: Emplotee){
  if(name){
    if(name.first){
      name.fisrt.startWith('AAA')
    }
  }
}

这样看着就比较复杂,我们有简单的方法:

function hasBadName(e: Employee){
	return e.name?.first?.startsWith('AAA')
}
//解释:第一步判断e.name是否存在,不存在则返回undefined;如果存在e.name继续以此方式向下判断  

来看看具体的用法:

interface Employee {
    name?: {
        last?: string,
        first?: string,
    }   
    salary: number
    bonus?: number        
}

function hasBadName(e: Employee){
    return e.name?.first?.startsWith('AAA')
}

console.log(hasBadName({
    name:{
        first: 'jhon',
        last: 'smith',
    },
    salary: 8000,
}))

//输出:false

console.log(hasBadName({
    name:{
        last: 'smith',
    },
    salary: 8000,
}))

//输出:undefined

这样我们就可以保护我们的程序不会挂掉

3. 2非空断言

在可选参数串联中,我们不能根本解决问题,所以我们需要使用来非空断言

只需要将3.1中的?给为!即可。

3. 3接口的拓展

我们可以理解为面向对象语言中的继承,老接口我们可以理解为父亲接口,新的接口我们理解为叫儿子接口为,儿子接口通过关键字extends继承父亲接口的属性和方法

实例:

//儿子接口
interface Employee extends HasName {   //接口的拓展:extends
    salary: number
    bonus?: number       
}

//父亲接口
interface HasName{
    name: {
        last: string,
        first: string,
    } 
}

//em1实现了接口Employee
const em1: Employee = {
    name:{
        first:'_moss',
        last: 'ice'
    },
    salary: 20000,
    bonus: 1000
}

console.log(em1)

输出结果:

{
  "name": {
    "first": "_moss",
    "last": "ice"
  },
  "salary": 20000,
  "bonus": 1000
} 
3. 4接口的并和类型断言
3.4.1接口的并

这里的“并”其实更像我们数学中的“交”

//接口的并和类型断言
//假设这是一个按钮
interface WxButton{
    visible: boolean,
    enabled:boolean,
    onClick():void,
}

//假设这是一个图片
interface WxImage{
    visible: boolean,
    src: string,
    withd:number,
    heigth: number,
}
    
 

这里可以看出来这里的"并"其实取两接口类型的公有部分

截屏2021-11-21 下午5.34.16
3.4.2类型断言

//接口的并和类型断言
interface WxButton{
    visible: boolean,
    enabled:boolean,
    onClick():void,
}

interface WxImage{
    visible: boolean,
    src: string,
    withd:number,
    heigth: number,
}

//类型断言
function processElement(e: WxButton | WxImage){
    if((e as any).onClick){
        const btn = e as WxButton
        btn.onClick()
    }else{
        const img = e as WxImage
        console.log(img.src)
    }
}


processElement({
    visible: true,
    src: 'this is src',
    withd: 20,
    heigth: 30,
})

processElement({
    visible: true,
    enabled: true,
    onClick(){
        console.log('onClick')
    }
})

//输出结果:
//  "this is src" 
//  "onClick"

二、类
1.类的定义

类描述了所创建的对象共同的属性和方法。

TypeScript 支持面向对象的所有特性,比如 类、接口等。

TypeScript 类定义方式如下:

class class_name {
  //作用域
}

类有三个重要的模块:

  1. 属性:

    字段是类声明的变量。

  2. 构造函数:

    类实例化时调用,可以为类的对象分配内存。

  3. 方法:

    方法为对象要执行的操作。

1.1类的属性(字段)
class Employee {
  name: string = 'ice_moss' //这里需要注意类字段需要给初始化
  salary: number  = 20000
}
1.2构造函数

我们声明一个Employeel类,构造函数在实例中初始化了类的字段name和salary,构造函数在初始化的时候使用关键字this:表示在该类下的字段

class Employee {
  name: string = 'ice_moss' 
  salary: number  = 20000
  constructor(name: string, salary: number){
    this.name = name
    this.salary = salary
  }
}

//当然,我们在可以在构造函数中使用关键字public,然后就可以不用在单独声明字段了:
class Employee {
  constructor(public name: string, public salary: number){
    this.name = name
    this.salary = salary
  }
//这样看着会更简洁
//其实这里还可以将直接写成:
  class Employee {
  constructor(public name: string, public salary: number){}
 
1.3方法
class Employee {
  constructor(public name: string, public salary: number){
    this.name = name
    this.salary = salary
  }
  getName():void{  //获取name
      console.log(this.name)
  }
  getSalary():void{  //获取salary
      console.log(this.salary)
  }
}

2.类的实例化
var object_name = new class_name([ arguments ])

依然是Employee类

class Employee {
  constructor(public name: string, public salary: number){
    this.name = name
    this.salary = salary
  }
  getName():void{  //获取name
      console.log(this.name)
  }
  getSalary():void{  //获取salary
      console.log(this.salary)
  }
}

//类的实例,需要使用关键字"new"
const em = new Employee('jhon', 9000)
console.log(em)
em.getName()
em.getSalary()


//输出结果:
Employee: {
  "name": "jhon",
  "salary": 9000
} 
 "jhon" 
 9000 
3.访问控制修饰符

TypeScript 中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。TypeScript 支持 3 种不同的访问权限。

public(默认) : 公有,可以在任何地方被访问。

protected : 受保护,可以被其自身以及其子类和父类访问。

private : 私有,只能被其定义所在的类访问。

下面继续看实例:

class Employee{
    private allocatebonus?: number   //allocatebonus是私有属性同时也是可选参数
    private bonus: number = 0
    constructor(public name:string, public salary:number){
        this.name = name
        this.salary = salary
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fikaa8XU-1637510973867)(/Users/feng/Library/Application Support/typora-user-images/截屏2021-11-21 下午7.08.59.png)]

此时我们在实例中是访问不到allocatebonus和bonus

3. getter/setter

我们在类中可以将函数写成调用字段的形式

class Employee{
    private allocatebonus?: number
    constructor(public name:string, public salary:number){
    }
    set bonus(v: number){
        this.allocatebonus = v
    }
    get bonus(){
        return this.allocatebonus || 0
    }
}

实例化:

const em = new Employee('jhon', 9000)
em.bonus = 2000
console.log(em)

输出:

Employee: {
  "name": "jhon",
  "salary": 9000,
  "allocatebonus": 2000
} 
4.类的继承(继承类的方法重写)

类的继承和接口的拓展相似,我们可以理解为面向对象语言中的继承,旧的类我们称为父类,新的类我们称为子类为,子类通过关键字extends继承父类的属性和方法

类继承后,子类可以对父类的方法重新定义,这个过程称之为方法的重写。

其中 super 关键字是对父类的直接引用,该关键字可以引用父类的属性和方法。

//父类
class Employee{
    private allocatebonus?: number
    constructor(public name:string, public salary:number){
    }
    set bonus(v: number){
        this.allocatebonus = v
    }
    get bonus(){
        return this.allocatebonus || 0
    }
    
}

//子类
class Manager extends Employee{
    private reporters: Employee[]
     constructor(name:string, salary:number) {
        super(name, salary)
        this.reporters = []
     }
     addReporters(e: Employee){
         this.reporters.push(e)
     }
}

const manager = new Manager('DF', 200000)

当类继承成功后我们可以看到如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oVNq5ZzR-1637510973871)(/Users/feng/Library/Application Support/typora-user-images/截屏2021-11-21 下午11.29.34.png)]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值