前言
前几篇文章写了我们在前端使用了大量的面向对象的思维来做前端开发,有很多朋友也展开了激烈的讨论,很有意思。 函数式编程的优势今天不讲,我们今天只讲讲 TypeScript 中面向对象在前端开发中怎么用,有什么用。
那就开始吧,首先:)
> 文中的代码都是直接在markdown中敲出来的,没有经过tsc编译验证,可能存在一些小问题,如果你发现哪里不对,欢迎评论。
你对象呢?
面向对象是一种抽象的思维,并不是一个很新鲜的词了。之所以在前端很少看到大量的面向对象,我想跟 JavaScript 这个狗东西有很大的关系。 那么在 TypeScript 中如何来用正确的姿势面向对象呢?
面向对象又有哪些功能和优势呢?
继承 extends
所谓继承,就好比你父亲本身已经有了很多强大的人脉背景以及资源,你不再需要自己去努力和维护,但你需要使用的时候,可以直接使用。
而且,如果你很多兄弟姐妹都有了一些共同的人脉关系后,家里就可以发展成为整个家庭的人脉关系,一遍整个家族都能来共享这些人脉关系。
// 父亲
class Dad {
// 父亲的车
car!: Car;
// 父亲会唱歌
sing() {
console.log("I can Sing!")
}
// 父亲会跳舞 但是私有的能力 不能被继承
private jump() {
console.log("Father can jump!")
}
}
// 孩子们
class Son extends Dad {
playGame() {
console.log("Son can play games!")
}
}
const son = new Son();
console.log(son.car) //可以使用 继承了父亲的车
son.sing() // 可以使用 继承了父亲唱歌的能力
son.jump() // 报错 没有这个能力 父亲不允许儿子继承跳舞的能力
son.playGame() // 可以使用 儿子自己学会的能力
在这里,如果其他儿子都会打游戏,那么可以把 playGame()
移动到 Dad
类中,所有的子类中就不再需要写这一部分了,是不是很Nice?
抽象 abstract
抽象类这个东西很有意思,可以认为,父亲对孩子们抱有一些会打球的希望,虽然自己不会,但是期望孩子们能自己学会,免得孩子们的女朋友想看孩子们打球的时候,孩子们没这个技能会分手。
// 父亲
abstract class Dad {
// 父亲喜欢打球 但是自己不会 于是期望孩子们自己学会打球
abstract playBall()
}
// 大儿子
class FirstSon extends Dad {
playBall() {
console.log("I can play basketball!")
}
}
// 小儿子
class SecondSon extends Dad {
playBall() {
console.log("I can play football!")
}
}
class Girl {
// 想看打球 跟这个父亲说
watchPlayBall(boy: Dad) {
boy.playBall()
}
}
const firstSon = new FirstSon();
const secondSon = new SecondSon();
const girl = new Girl();
girl.watchPlayBall(firstSon) // 大儿子说自己会打篮球
girl.watchPlayBall(secondSon) // 小儿子说自己会踢足球
看,相亲广场上女孩一眼相中了 Dad
的两个孩子,但是女孩想看看这俩孩子打球时候的样子,于是就有了上面的场景。
接口和实现 interface implements
// 英语水平报告的接口
interface IEnglishReport {
getSpeakSkillStatus(): string;
}
// 普通程序员
class Programer implements IEnglishReport {
getSpeakSkillStatus() {
return "糟糕"
}
}
// 英语专业的高材生
class EnglishStudent implements IEnglishReport {
getSpeakSkillStatus() {
return "优秀"
}
}
// 英语水平调查 要求被检查的人必须携带英语水平报告(实现IEnglishReport接口)
function checkReport(user: IEnglishReport) {
if (user.getSpeakSkillStatus() === "糟糕") {
return "报告不合格"
}
return "报告合格"
}
const hamm = new Programer();
const selina = new EnglishStudent();
checkReport(hamm) // 英语说的水平糟糕 报告不合格
checkReport(selina) // 报告合格
如上,招聘的时候HR做了个英语水平的调查,需要英语的说和写的水平都在线,不能糟糕。 于是 Hamm 报告不合格,就被卡住了。
泛型 <!--?-->
我们现在提供了一个对这些说英语能力比较糟糕的人进行培训的方法,让他们达到一个优秀的水平。
interface IEnglishReport {
getLevel(): string;
setLevel(level: string);
}
// 普通程序员
class Programer implements IEnglishReport {
// 编程水平
programingLevel = '优秀'
// 英语水平
englishLevel = '糟糕'
getLevel(): string {
return this.englishLevel;
}
setLevel(_level: string) {
this.englishLevel = _level;
}
}
// 英语专业的高材生
class EnglishStudent implements IEnglishReport {
// 英语水平
level = '优秀'
getLevel(): string {
return this.getLevel()
}
setLevel(level: string) {
this.level = level
}
}
// 英语培训 返回一个深造之后的用户
function train<t extends ienglishreport>(user: T): T {
// 每个用户把自己的证书都不知道藏哪了
// 所以要求他们必须提供一个查询英语等级的方法
if (user.getLevel() === "糟糕") {
console.log("培训成功")
// 提供一个培训后新证书的邮寄地址
user.setLevel("优秀")
return user;
}
console.log("英语水平在线 无需培训")
return user;
}
const hamm = new Programer();
const selina = new EnglishStudent();
console.log(hamm.englishLevel) // 糟糕
console.log(selina.level) // 优秀
const newHamm = train(hamm) // 培训成功
const newSelina = train(selina) // 无需培训
console.log(newHamm.englishLevel) // 优秀
console.log(newSelina.level) // 优秀
That's all
我们简单用代码来聊了聊 TypeScript 在面向对象中的一些使用方式,如果你理解了,欢迎给点一个大大的赞~
我们最近在使用 vue3
TypeScript
ElementPlus
Java
SpringBoot
JPA
等技术栈实现一套基于面向对象的前后端统一开发全栈项目,欢迎关注:
前端:https://github.com/HammCn/AirPower4T
后端:https://github.com/HammCn/AirPower4J