typescript第三天—接口和类

2023-11-11

接口

作一个简历的自动筛选程序,很简单。年龄小于 25 岁,胸围大于 90 公分的,可以进入面试环节。我们最开始的写法是这样的。(新建一个文件 Demo8.ts,然后编写如下代码)

const screenResume = (name: string, age: number, bust: number) => {
  age < 24 && bust >= 90 && console.log(name + "进入面试");
  age > 24 || (bust < 90 && console.log(name + "你被淘汰"));
};

screenResume("大脚", 18, 94);

写好后,好像我们的程序写的不错,可以在终端中使用ts-node demo8.ts进行查看。这时候老板又增加了需求,说我必须能看到这些女孩的简历。于是你又写了这样一个方法。

const getResume = (name: string, age: number, bust: number) => {
  console.log(name + "年龄是:" + age);
  console.log(name + "胸围是:" + bust);
};
getResume("大脚", 18, 94);

这时候问题来了,程序开发中一直强调“代码重用”,两个方法用的类型注解一样,需要作个统一的约束。大上节课我们学了一个类型别名的知识可以解决代码重复的问题,这节课我们就学习一个更常用的语法接口(Interface).

我们可以把这两个重复的类型注解,定义成统一的接口。代码如下:

interface Girl {
  name: string;
  age: number;
  bust: number;
}

有了接口后,我们的程序也要作一些修改,需要写成下面的样子。这样就更像是面向对象编程了。

const screenResume = (girl: Girl) => {
  girl.age < 24 && girl.bust >= 90 && console.log(girl.name + "进入面试");
  girl.age > 24 || (girl.bust < 90 && console.log(girl.name + "你被淘汰"));
};

const getResume = (girl: Girl) => {
  console.log(girl.name + "年龄是:" + girl.age);
  console.log(girl.name + "胸围是:" + girl.bust);
};
const girl = {
  name: "大脚",
  age: 18,
  bust: 94,
};

screenResume(girl);
getResume(girl);

这时候我们代码就显得专业了很多,以后再用到同样的接口也不怕了,直接使用girl就可以了。

接口和类型别名的区别

用起来基本一样,但是也有少许的不同。

类型别名可以直接给类型,比如string,而接口必须代表对象。

比如我们的类型别名可以写出下面的代码:

type Girl1 = stirng;

但是接口就不能这样写,它必须代表的是一个对象,也就是说,你初始化girl的时候,必须写出下面的形式.

const girl = {
  name: "大脚",
  age: 18,
  bust: 94,
};

非必选值

老板又有了新的要求,要求尽量能看到小姐姐的腰围,但是不作强制要求,就是可选值吗。那接口如何定义那?其实typeScript已经为我们准备好了相应的办法,就是在号前加一个?

比如把Girl的接口写成这样。

interface Girl {
  name: string;
  age: number;
  bust: number;
  waistline?: number;
}

然后我们再修改一下getResume方法,写成这样。

const getResume = (girl: Girl) => {
  console.log(girl.name + "年龄是:" + girl.age);
  console.log(girl.name + "胸围是:" + girl.bust);
  girl.waistline && console.log(girl.name + "腰围是:" + girl.waistline);
};

这时候在定义girl对象的时候,就可以写saistline(腰围),也可以不写了。

接口允许加入任意值

简历一般是有自由发挥的空间的,所以这时候需要一些任意值,就是自己愿意写什么就写什么。这时候interface接口也是支持的。方法如下: 我们接着上节课的代码,新建一个Demo9.ts,然后把上节课代码拷贝过来。

interface Girl {
name: string;
age: number;
bust: number;
waistline?: number;
[propname: string]: any;
}
这个的意思是,属性的名字是字符串类型,属性的值可以是任何类型。

这时候我们在对象里给一个性别,代码如下:

const girl = {
  name: "大脚",
  age: 18,
  bust: 94,
  waistline: 21,
  sex: "女",
};

再修改一下代码,这首就没有错误了。

const getResume = (girl: Girl) => {
  console.log(girl.name + "年龄是:" + girl.age);
  console.log(girl.name + "胸围是:" + girl.bust);
  girl.waistline && console.log(girl.name + "腰围是:" + girl.waistline);
  girl.sex && console.log(girl.name + "性别是:" + girl.sex);
};

这时候我们的程序是不报错的,但是如果我们去掉刚才的设置,就会报错。

[propname:string]:any;  //去掉

在接口里写方法

接口里不仅可以存属性,还可以存方法,比如这时候有个say()方法,返回值是string类型。这时候你就不要再想成简历了,你需要更面向对象化的编程,想象成一个人。

interface Girl {
  name: string;
  age: number;
  bust: number;
  waistline?: number;
  [propname: string]: any;
  say(): string;
}

加上这个say()方法后,程序马上就会报错,因为我们对象里没有 say 方法。那我们就要给对象一个 say 方法

const girl = {
  name: "大脚",
  age: 18,
  bust: 94,
  waistline: 21,
  sex: "女",
  say() {
    return "欢迎光临 ,红浪漫洗浴!!";
  },
};

接口和类的约束

我们都知道 JavaScript 从ES6里是有类这个概念的,类可以和接口很好的结合,我们先来看一个例子。下面的

class XiaoJieJie implements Girl {}

这时候类会直接报错,所以我们需要把这个类写的完全点。

class XiaoJieJie implements Girl {
  name = "刘英";
  age = 18;
  bust = 90;
  say() {
    return "欢迎光临 ,红浪漫洗浴!!";
  }
}

接口间的继承

接口也可以用于继承的,比如你新写一个Teacher接口,继承于Person接口。

interface Teacher extends Girl {
  teach(): string;
}

比如这时候老板说了,只看 Teacher 级别的简历,那我们需要修改getResume()方法。

const getResume = (girl: Teacher) => {
  console.log(girl.name + "年龄是:" + girl.age);
  console.log(girl.name + "胸围是:" + girl.bust);
  girl.waistline && console.log(girl.name + "腰围是:" + girl.waistline);
  girl.sex && console.log(girl.name + "性别是:" + girl.sex);
};

修改后,你就会发现下面我们调用getResume()方法的地方报错了,因为这时候传的值必须有Teach方法,

getResume(girl);
修改girle对象,增加teach()方法,这时候就不会报错了。

const girl = {
  name: "大脚",
  age: 18,
  bust: 94,
  waistline: 21,
  sex: "女",
  say() {
    return "欢迎光临 ,红浪漫洗浴!!";
  },
  teach() {
    return "我是一个老师";
  },
};

学会了接口,你还需要明白一件事,就是接口只是对我们开发的约束,在生产环境中并没有体现。也可以说接口只是在 TypeScript 里帮我们作语法校验的工具,编译成正式的js代码,就不会有任何用处了。

类的基本使用

定义一个最简单的Lady类,这里要使用关键字class,类里边有姓名属性和一个得到姓名的方法,代码如下:

class Lady {
  content = "Hi,帅哥";
  sayHello() {
    return this.content;
  }
}

const goddess = new Lady();
console.log(goddess.sayHello());

写完代码后,可以使用ts-node demo10.ts来查看一下结果。

类的继承

这里提前说一下 TypeScrip 的继承和ES6中的继承是一样的。关键字也是extends,比如我们这里新建一个XiaoJieJie的类,然后继承自Lady类,在XiaoJieJie类里写一个新的方法,叫做sayLove,具体代码如下。

class Lady {
  content = "Hi,帅哥";
  sayHello() {
    return this.content;
  }
}
class XiaoJieJie extends Lady {
  sayLove() {
    return "I love you";
  }
}

const goddess = new XiaoJieJie();
console.log(goddess.sayHello());
console.log(goddess.sayLove());

类写好以后,我们声明的对象是XiaoJieJie这个类,我们同时执行sayHello()sayLove()都是可以执行到的,这说明继承起作用了。

类的重写

重写就是子类可以重新编写父类里边的代码。
现在我们在XiaoJieJie这个类里重写父类的sayHello()方法,比如现在我们觉的叫的不够亲切,我们改成下面这个样子。

class XiaoJieJie extends Lady {
  sayLove() {
    return "I love you!";
  }
  sayHello() {
    return "Hi , honey!";
  }
}

super关键字

比如我们还是想使用Lady类中说的话,但是在后面,加上你好两个字就可以了。这时候就可以使用super关键字,它代表父类中的方法。那我们的代码就可以写成这个样子了。

class XiaoJieJie extends Lady {
  sayLove() {
    return "I love you!";
  }
  sayHello() {
    return super.sayHello() + "。你好!";
  }
}

类的访问类型

类的访问类型就是基于三个关键词privateprotectedpublic,也是三种访问类型

一个简单的类

在新的文件里,我们定义一个 Person 类,然后使用这个类的对象,进行赋值,最后打印在控制台上。具体代码如下:

class Person {
  name: string;
}

const person = new Person();
person.name = "jspang.com";

console.log(person.name);

写完后我们直接可以在Terminal(中),输入ts-node demo11.ts进行查看结果,结果会打印出jspang.com。

public访问属性讲解

这时候可以打出jspang.com是因为我们如果不在类里对name的访问属性进行定义,那么它就会默认是public访问属性。

这就相当于下面的这段代码:

class Person {
    public name:string;
}

public从英文字面的解释就是公共的或者说是公众的,在程序里的意思就是
允许在类的内部和外部被调用.

比如我们在类内调用,我们在写一个sayHello的方法,代码如下:

class Person {
    public name:string;
    public sayHello(){
        console.log(this.name + ' say Hello')
    }
}

这是的this.name就是类的内部调用。我们在下面在执行一下这个方法person.sayHello(),终端中可以看到一切正常运行了,顺利打印出了jspang.com say Hello这句话。

在类的外部调用,我们就可以很简单的看出来了,比如下面的代码,从注释横线下,全部是类的外部。

class Person {
    public name:string;
    public sayHello(){
        console.log(this.name + 'say Hello')
    }
}
//-------以下属于类的外部--------
const person = new Person()
person.name = 'jspang.com'
person.sayHello()
console.log(person.name)

结果我就不演示了,一定是可以被调用的,接下来我们再来看private属性。

private访问属性讲解

private 访问属性的意思是,只允许在类的内部被调用,外部不允许调用

比如现在我们把 name 属性改成private,这时候在类的内部使用不会提示错误,而外部使用VSCode直接会报错。

class Person {
    private name:string;
    public sayHello(){
        console.log(this.name + 'say Hello')  //此处不报错
    }
}
//-------以下属于类的外部--------
const person = new Person()
person.name = 'jspang.com'    //此处报错
person.sayHello()
console.log(person.name)  //此处报错

protected 访问属性讲解

protected 允许在类内及继承的子类中使用

做一个例子,把name的访问属性换成protected,这时候外部调用name的代码会报错,内部的不会报错,和private一样。这时候我们再写一个Teacher类,继承于Person,代码如下:

class Person {
    protected name:string;
    public sayHello(){
        console.log(this.name + 'say Hello')  //此处不报错
    }
}

class Teacher extends Person{
    public sayBye(){
        this.name;
    }
}

这时候在子类中使用this.name是不报错的。

类的构造函数

在页面里新建一个 Person 类,类的里边定义一个name,但是name我们并不给他值,然后我们希望在new出对象的时候,直接通过传递参数的形式,给name赋值,并打印出来。这时候我们就需要用到构造函数了,构造函数的关键字是constructor

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

}

const person= new Person('jspang')
console.log(person.name)

写完后使用ts-node demo12.ts进行查看,应该可以打出jspang的字样。这是最常规和好理解的写法,那有没有更简单的写法那?当然有。

class Person{
    constructor(public name:string){
    }
}

const person= new Person('jspang')
console.log(person.name)

这种写法就相当于你定义了一个name,然后在构造函数里进行了赋值,这是一种简化的语法,在工作中我们使用这种语法的时候会更多一些。

类继承中的构造器写法
普通类的构造器我们已经会了,在子类中使用构造函数需要用super()调用父类的构造函数。这时候你可能不太理解我说的话,我们还是通过代码来说明(详细说明在视频中讲述)。

class Person{
    constructor(public name:string){}
}

class Teacher extends Person{
    constructor(public age:number){
        super('jspang')
    }
}

const teacher = new Teacher(18)
console.log(teacher.age)
console.log(teacher.name)

这就是子类继承父类并有构造函数的原则,就是在子类里写构造函数时,必须用super()调用父类的构造函数,如果需要传值,也必须进行传值操作。就是是父类没有构造函数,子类也要使用super()进行调用,否则就会报错。

class Person{}

class Teacher extends Person{
    constructor(public age:number){
        super()
    }
}

const teacher = new Teacher(18)
console.log(teacher.age)

类的 Getter、Setter 和 static 使用

学了类的访问类型private,那这个东西如何使用?其实他的最大用处是封装一个属性,然后通过 Getter 和 Setter 的形式来访问和修改这个属性。

类的 Getter 和 Setter

声明一个XiaoJieJie(小姐姐)类,都知道小姐姐的年龄是不能随便告诉人,所以使用了private,这样别人就都不知道她的真实年龄,而只有她自己知道。

class Xiaojiejie {
  constructor(private _age:number){}
}

如果别人想知道,就必须通过getter属性知道,注意我这里用的是属性,对他就是一个属性。getter属性的关键字是get,后边跟着类似方法的东西,但是你要注意,它并不是方法,归根到底还是属性。

class Xiaojiejie {
  constructor(private _age:number){}
  get age(){
      return this._age
  }
}

const dajiao = new Xiaojiejie(28)

console.log(dajiao.getAge)

这时候你会觉的这么写不是多此一举吗?玄妙就在于getter里,我们可以对_age进行处理,比如别人问的时候我们就偷摸的减少 10 岁。代码可以写成这样。

class Xiaojiejie {
  constructor(private _age:number){}
  get age(){
      return this._age-10
  }
}

这时候大脚的年龄就编程了迷人的 18 岁,是不是通过这个小例子,一下子就明白了privategetter的用处。 _age是私有的,那类的外部就没办法改变,所以这时候可以用setter属性进行改变,代码如下:

class Xiaojiejie {
  constructor(private _age:number){}
  get age(){
      return this._age-10
  }
  set age(age:number){
    this._age=age
  }
}

const dajiao = new Xiaojiejie(28)
dajiao.age=25

console.log(dajiao.age)
其实setter也是可以保护私有变量的,现在大脚的年龄输出是 15 岁,这肯定不行,不符合法律哦,这样是我们在setter里给他加上个 3 岁,就可以了。

 set age(age:number){
    this._age=age+3
  }

这是想通过这个例子让小伙伴们清楚的明白getter和setter的使用,很多小伙伴刚学这部分,都不太清楚为什么要使用getter和setter,你也能更清楚private访问类型的意义。

类中的 static

学习类,都知道要想使用这个类的实例,就要先New出来(),但有时候人们就是喜欢走捷径,在们有对象的情况下,也想享受青春的躁动,有没有方法?肯定是有方法的。

比如我们先写一下最常规的写法:

class Girl {
  sayLove() {
    return "I Love you";
  }
}

const girl = new Girl();
console.log(girl.sayLove());

但是现在你不想new出对象,而直接使用这个方法,那TypeScript为你提供了快捷的方式,用static声明的属性和方法,不需要进行声明对象,就可以直接使用,代码如下。

class Girl {
  static sayLove() {
    return "I Love you";
  }
}
console.log(Girl.sayLove());

这节课我们就学到了这里,复习一下,我们学了private的使用意义,学了getter和setter属性,还学习了静态修饰符static,这样就不用 new 出对象就可以使用类里的方法了。

类的只读属性和抽象类

抽象类很父类很像,都需要继承,但是抽象类里一般都有抽象方法。继承抽象类的类必须实现抽象方法才可以。在讲抽象类之前,我想把上节课我遗忘的一个知识点给大家不上,那就是类里的只读属性readonly.

类里的只读属性 readonly

新建一个文件Demo14.ts,然后写下面一个类,并进行实例化和赋值操作,代码如下:

class Person {
    constructor(public name:string ){ }
}

const person = new Person('jspang')
console.log(person.name)
写完后我们可以在终端(Terminal)中看一下结果,结果就应该是jspang。

比如我现在有一个需求,就是在实例化对象时赋予的名字,以后不能再更改了,也就是我们常说的只读属性。我们先来看现在这种情况是可以随意更改的,比如我写下面的代码。

class Person {
    constructor(public name:string ){ }
}

const person = new Person('jspang')
person.name= '谢广坤'
console.log(person.name)

这时候就可以用一个关键词readonly,也就是只读的意思,来修改Person类代码。

class Person {
    public readonly _name :string;
    constructor(name:string ){
        this._name = name;
    }
}

const person = new Person('jspang')
person._name= '谢广坤'
console.log(person._name)

这样写完后,VSCode就回直接给我们报错,告诉我们_name属性是只读属性,不能修改。

抽象类的使用

什么是抽象类那?我给大家举个例子,比如我开了一个红浪漫洗浴中心,里边有服务员,有初级技师,高级技师,每一个岗位我都写成一个类,那代码就是这样的

class Waiter {}

class BaseTeacher {}

class seniorTeacher {}

我作为老板,我要求无论是什么职位,都要有独特的技能,比如服务员就是给顾客倒水,初级技师要求会泰式按摩,高级技师要求会 SPA 全身按摩。这是一个硬性要求,但是每个职位的技能有不同,这时候就可以用抽象类来解决问题。

抽象类的关键词是abstract,里边的抽象方法也是abstract开头的,现在我们就写一个Girl的抽象类。

abstract class Girl{
    abstract skill()  //因为没有具体的方法,所以我们这里不写括号

}

有了这个抽象类,三个类就可以继承这个类,然后会要求必须实现skill()方法,代码如下:

abstract class Girl{
    abstract skill()  //因为没有具体的方法,所以我们这里不写括号

}

class Waiter extends Girl{
    skill(){
        console.log('大爷,请喝水!')
    }
}

class BaseTeacher extends Girl{
    skill(){
        console.log('大爷,来个泰式按摩吧!')
    }
}

class seniorTeacher extends Girl{
    skill(){
        console.log('大爷,来个SPA全身按摩吧!')
    }
}

学习视频:https://www.bilibili.com/video/BV1qV41167VD?p=8
学习资料:https://jspang.com/detailed?id=63#toc226

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

typescript第三天—接口和类 的相关文章

随机推荐

  • hadoop (1.0.4) Path 详解

    Path 对路径进行解析 将参数转换为标准的URI格式 对Path的参数作判断 标准化 字符化等操作 为了便于理解Path 各位可以先参看URI的详解 链接http www cnblogs com springside5 archive 2
  • Hbase 单机环境搭建

    大数据处理场景 比如我要想对十几亿数据进行排序 肯定不能放在关系型数据库排序 首当其冲就要想到一个能高效存储与高效读取的数据库 这里我想到了分布式数据库Hbase 今天我们就只讲下Hbase安装 后面会讲到数据读取出来了如何高效进行排序 H
  • LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置

    LeetCode 34 在排序数组中查找元素的第一个和最后一个位置 解题思路 这里先使用二分法寻找到第一个位置 在从第一个位置开始挨个 循环 寻找最后一个位置 当然 最后一个位置也可以使用二分的方法完成 代码实现 class Solutio
  • Echarts中国地图的china.js下载

    今天用到了Echarts的中国地图map 但Echarts官网的地图js已经停止提供下载了 找了下其他的链接放到这里 一些其他会用到的js文件也在里面可以找到 省的下次用现找 https github com apache incubato
  • Linux 搭建Redis 哨兵集群

    目录 1 安装环境 2 下载安装包 3 安装依赖环境和编译 4 启动 5 集群搭建 6 启动哨兵 7 设置开机自启动 8 redis卸载 1 安装环境 阿里云centos7 9版本 2 下载安装包 地址 Index of releases
  • 代码覆盖生态系统的库和软件包

    如果您已经编写了测试驱动的代码已有一段时间了 那么您将了解代码覆盖率 也称为测试覆盖率 如果您不熟悉该术语 则有两个简短定义 维基百科将其定义为 一种度量 用于描述特定测试套件运行时程序源代码的执行程度 根据Martin Fowler的说法
  • 深入学习jquery源码之append()和prepend()

    深入学习jquery源码之append 和prepend append content fn 概述 向每个匹配的元素内部追加内容 这个操作与对指定的元素执行appendChild方法 将它们添加到文档中的情况类似 参数 content St
  • 《算法图解》总结第 2 章:数组和链表,选择排序

    仅用于记录学习 欢迎批评指正 大神勿喷 系列文章目录 算法图解 总结第 1 章 二分查找 大O表示法 算法图解 总结第 2 章 数组和链表 选择排序 算法图解 总结第 3 章 while循环 递归 栈 算法图解 总结第 4 章 分而治之 快
  • VSCode LSP 语言服务器协议总结

    为什么使用语言服务器协议 LSP Language Server Protocol 语言服务器是一种特殊的 Visual Studio Code 扩展 可为许多编程语言提供编辑体验 使用语言服务器 您可以实现自动完成 错误检查 诊断 跳转到
  • android的fragment用法,Android Fragment用法知识点的讲解

    Android Fragment用法的讲解 碎片 它的出现是为了更好展示UI的设计 让程序更加得到充分的展示 Fragment的出现 如微信的额主界面包含多个Fragment 使得微信功能更加简洁明了 Fragment组件 Fragment
  • Nim游戏(C++)

    题目 给定 n 堆石子 两位玩家轮流操作 每次操作可以从任意一堆石子中拿走任意数量的石子 可以拿完 但不能不拿 最后无法进行操作的人视为失败 问如果两人都采用最优策略 先手是否必胜 输入格式 第一行包含整数 n 第二行包含 n 个数字 其中
  • 微信小程序开发笔记—设置页面密码

    文章目录 一 功能概述 二 实现效果 三 实现方法 1 新建个人登陆页面 2 设计密码获取判别函数和响应函数 1 定义变量 2 设计密码获取判别函数 3 设计响应函数 3 设计页面内容 1 input组件设计 2 button组件设计 四
  • 如何显示远程桌面_库卡机器人之远程桌面RDP

    前面已经介绍过使用VNC和RSV来实现库卡机器人的远程连接 其实还有一些方法 比如Teamviewer或Virture Remote Pendant 简称VRP 这里就不再介绍如何来实现 今天主要介绍通过windows自带的RDP来实现这种
  • Verilog 学习笔记(4)——语句块,多路分支语句、循环语句、连续赋值语句

    本章主要讲解Verilog语言中的语句部分 Verilog 语句块主要包括顺序块和并行块 语句类型有多路分支语句 case语句 casex casez 语句 循环语句 while 循环 for 循环 repeat 循环 forever 循环
  • 前端18K面试题总览,往这方面准备就对了

    Vue面试题 生命周期函数面试题 1 什么是 vue 生命周期 2 vue生命周期的作用是什么 3 第一次页面加载会触发哪几个钩子 4 简述每个周期具体适合哪些场景 5 created和mounted的区别 6 vue获取数据在哪个周期函数
  • AI数字人应该怎么制作?详细教程

    现在市面上有很多可以制作AI数字人的平台工具 本文主要针对使用腾讯智影来制作数字人 附免费教程 1 腾讯智影介绍 腾讯推出的在线智能视频创作平台 智影是一款云端智能视频创作工具 无需下载即可通过PC浏览器访问 支持视频剪辑 素材库 文本配音
  • C语言之 printf() 和 scanf() 函数详解

    文章目录 前言 一 printf 函数详解 1 函数原型 2 参数说明符详解 3 代码示例及易错点示例 二 scanf 函数详解 1 函数原型 2 参数说明符详解 3 代码示例及易错点示例 前言 printf scanf 两个函数相信大家并
  • 产品经理需要向上思考

    上一篇文章说了产品经理如何锻炼自己看透事物本质的能力 王诗沐老师在其 幕后产品 一书中还提到向上思考能力 读完后对我有一定的启发 我加一些自己的思考 和大家聊聊这个话题 很多人在产品经理面试的时候 可能会被问到这样一个题目 就是你如何看待X
  • 数据库第五周实验——单表查询——例题实现

    文章目录 一 选择表中的若干列 1 查询指定列 2 查询全部列 3 查询经过计算的值 二 选择表中的若干元组 1 消除取值重复的行 DISTINCT 2 查询满足条件的元组 WHERE 1 比较大小 2 确定范围 3 确定集合 4 字符匹配
  • typescript第三天—接口和类

    接口 作一个简历的自动筛选程序 很简单 年龄小于 25 岁 胸围大于 90 公分的 可以进入面试环节 我们最开始的写法是这样的 新建一个文件 Demo8 ts 然后编写如下代码 const screenResume name string