10.【TypeScript 教程】类(Class)

自 ES6 起,终于迎来了 class,对于开发者来说,终于可以使用基于类的面向对象式编程。TypeScript 在原 ES6 中类的基础上,还添加了一些新的功能,比如几种访问修饰符,这是在其他面向对象语言中早就实现了的。

JavaScript 的类作为语法糖,我们不但需要知道怎么去使用,还应该了解其本质,涉及到原型的部分希望大家能深入理解。

1. 解释

类描述了所创建的对象共同的属性和方法。通过 class 关键字声明一个类,主要包含以下模块:

  • 属性
  • 构造函数
  • 方法

2. 类的本质

JavaScript 中,生成实例对象可以通过构造函数的方式:

实例演示

function Calculate (x, y) {this.x = xthis.y = y
}Calculate.prototype.add = function () {return this.x + this.y
}var calculate = new Calculate(1, 2)
console.log(calculate.add()) // 3

如果通过 class 关键字进行改写:

实例演示

class Calculate {// 类的属性public x: numberpublic y: number// 构造函数constructor(x: number, y: number) {this.x = xthis.y = y}// 类的方法add () {return this.x + this.y}
}const calculate = new Calculate(1, 2)
console.log(calculate.add()) // 3console.log(typeof Calculate) // 'function'
console.log(Calculate === Calculate.prototype.constructor) // true

代码解释:

最后一行,可以看出,类指向其构造函数本身,class 关键字可以看做是一个语法糖。

constructor() 方法是类的默认方法,通过 new 来生成对象实例时,自动调用该方法。换句话说,constructor() 方法默认返回实例对象 this

3. 类的继承

基于类的程序设计中一种最基本的模式是允许使用继承来扩展现有的类,这样可以抽出公共部分让子类复用。

使用 extends 关键字来实现继承:

实例演示

// 继承 JavaScript 内置的 Date 对象
class LinDate extends Date {getFormattedDate() {var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];return this.getDate() + "-" + months[this.getMonth()] + "-" + this.getFullYear();}
}const date = new LinDate()console.log(date.getFullYear());     // 2024
console.log(date.getFormattedDate()) // 11-Jan-2024

代码解释: LinDate 继承了 Date 的功能,可以使用父类 Date 的方法 getFullYear(),也可以使用自身的方法 getFormattedDate()

子类在 constructor 内中使用 super() 方法调用父类的构造函数,在一般方法内使用 super.method() 执行父类的方法。

实例演示

class Animal {public name:stringconstructor(name: string) { this.name = name }move(distance: number = 0) {console.log(`${this.name} moved ${distance}m.`)}
}class Dog extends Animal {constructor(name: string) { // 调用父类的构造函数super(name)}move(distance = 10) {console.log('bark...')// 执行父类的方法super.move(distance) }
}const dog: Animal = new Dog('Coco')dog.move() // Coco moved 10m.

代码解释:

第 16 行,通过 super() 调用了父类的构造函数。

第 22 行,通过 super 关键字调用父类的方法。

4. 访问修饰符

TypeScript 可以使用四种访问修饰符 public、protected、private 和 readonly。

4.1 public

TypeScript 中,类的成员全部默认为 public,当然你也可以显式的将一个成员标记为 public,标记为 public 后,在程序类的外部可以访问。

class Calculate {// 类的属性public x: numberpublic y: number// 构造函数public constructor(x: number, y: number) {this.x = xthis.y = y}public add () {return this.x + this.y}
}

4.2 protected

当成员被定义为 protected 后,只能被类的内部以及类的子类访问

class Base {protected baseUrl: string = 'http://api.com/'constructor() {}protected request(method: string) {const url = `${this.baseUrl}${method}`// TODO 封装基础的 http 请求}
}class Address extends Base {get() {return this.request('address')}
}

代码解释:

第 2 行,Base 类的属性 baseUrl 被定义为受保护的,那么第 7 行该属性在类中被访问是可以的。

第 14 行,因 Address 类是 Base 类的子类,在子类中允许访问父类中被定义为受保护类型的方法 request() 。

4.3 private

当类的成员被定义为 private 后,只能被类的内部访问

class Mom {private labour() {return 'baby is coming'}
}class Son extends Mom {test () {this.labour() // Error, Property 'labour' is private and only accessible within class 'Mom'}
}

代码解释:

第 9 行,父类中的 labour() 方法被定义为私有方法,只能在父类中被使用,子类中调用报错。

4.4 readonly

通过 readonly 关键字将属性设置为只读的。只读属性必须在声明时或构造函数里被初始化。

class Token {readonly secret: string = 'xjx*xh3GzW#3'readonly expired: numberconstructor (expired: number) {this.expired = expired} 
}const token = new Token(60 * 60 * 24)
token.expired = 60 * 60 * 2 // Error, expired 是只读的

代码解释:

最后一行,因 Token 类的属性 expired 被设置为只读属性,不可被修改。

5. 静态方法

通过 static 关键字来创建类的静态成员,这些属性存在于类本身上面而不是类的实例上

class User {static getInformation () {return 'This guy is too lazy to write anything.'}
}User.getInformation() // OKconst user = new User()
user.getInformation() // Error 实例中无此方法

代码解释: getInformation() 方法被定义为静态方法,只存在于类本身上,类的实例无法访问。

静态方法调用同一个类中的其他静态方法,可使用 this 关键字。

class StaticMethodCall {static staticMethod() {return 'Static method has been called'}static anotherStaticMethod() {return this.staticMethod() + ' from another static method'}}

代码解释: 静态方法中的 this 指向类本身,而静态方法也存在于类本身,所以可以在静态方法中用 this 访问在同一类中的其他静态方法。

非静态方法中,不能直接使用 this 关键字来访问静态方法。而要用类本身或者构造函数的属性来调用该方法:

class StaticMethodCall {constructor() {// 类本身调用console.log(StaticMethodCall.staticMethod())// 构造函数的属性调用console.log(this.constructor.staticMethod())}static staticMethod() {return 'static method has been called.'}
}

代码解释: 类指向其构造函数本身,在非静态方法中,this.constructor === StaticMethodCall 为 true, 也就是说这两种写法等价。

6. 抽象类

抽象类作为其它派生类的基类使用,它们一般不会直接被实例化,不同于接口,抽象类可以包含成员的实现细节。

abstract 关键字是用于定义抽象类和在抽象类内部定义抽象方法。

abstract class Animal {abstract makeSound(): void;move(): void {console.log('roaming the earch...');}
}const animal = new Animal() // Error, 无法创建抽象类实例

通常我们需要创建子类继承抽象类,将抽象类中的抽象方法一一实现,这样在大型项目中可以很好的约束子类的实现。

class Dog extends Animal {makeSound() {console.log('bark bark bark...')}
}const dog = new Dog()dog.makeSound()  // bark bark bark...
dog.move()       // roaming the earch...

7. 把类当做接口使用

类也可以作为接口来使用,这在项目中是很常见的。

class Pizza {constructor(public name: string, public toppings: string[]) {}
}class PizzaMaker {// 把 Pizza 类当做接口static create(event: Pizza) {return new Pizza(event.name, event.toppings)}
}const pizza = PizzaMaker.create({ name: 'Cheese and nut pizza', toppings: ['pasta', 'eggs', 'milk', 'cheese']
})

第 7 行,把 Pizza 类当做接口。

因为接口和类都定义了对象的结构,在某些情况下可以互换使用。如果你需要创建一个可以自定义参数的实例,同时也可以进行类型检查,把类当做接口使用不失为一个很好的方法。

这就是 TypeScript 的强大功能,而且非常灵活,拥有全面的面向对象设计和通用的类型检查

8. 小结

本节介绍了类的本质及其使用方法,需要注意:

  • 类指向其构造函数本身。
  • 静态方法存在于类本身上面而不是类的实例上。
  • 抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。
  • TypeScript 新增了 public、protected、private 等访问修饰符。
  • 子类继承父类时,在其构造函数 constructor() 中不要忘了 super() 方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/613330.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智慧校园实验室安全综合管理平台如何保障实验室安全?

一、建设思路 实验室安全综合管理平台是基于以实验室安全,用现代化管理思想与人工智能、大数据、互联网技术、物联网技术、云计算技术、人体感应技术、语音技术、生物识别技术、手机APP、自动化仪器分析技术有机结合,通过建立以实验室为中心的管理体系&…

2019年认证杯SPSSPRO杯数学建模D题(第一阶段)5G时代引发的道路规划革命全过程文档及程序

2019年认证杯SPSSPRO杯数学建模 5G下十字路口车辆通行效率的讨论和建模 D题 5G时代引发的道路规划革命 原题再现: 忙着回家或上班的司机们都知道交通堵塞既浪费时间又浪费燃料,甚至有的时候会带来情绪上的巨大影响,引发一系列的交通问题。…

python使用单例模式加载config.ini配置文件

在Python中,可以使用单例模式来加载和管理配置文件。下面是一个示例代码: import configparserclass ConfigLoader:__instance Nonedef __init__(self):if ConfigLoader.__instance is not None:raise Exception("ConfigLoader is a singleton cl…

使用Docker运行SRS Stack

SRS Stack | SRS (ossrs.net) Docker​ 推荐使用Docker运行SRS Stack: docker run --restart always -d -it --name srs-stack -v $HOME/data:/data \-p 2022:2022 -p 2443:2443 -p 1935:1935 -p 8000:8000/udp -p 10080:10080/udp \registry.cn-hangzhou.aliyun…

springcloud gateway动态路由

动态每秒调用数据库,加载路由信息到路由定义(RouteDefinition)中 主要是继承 RouteDefinitionRepository接口: Component Slf4j public class DbRouteDefinitionRepository implements RouteDefinitionRepository {Resourcepri…

Gradle的安装及换源

Gradle的安装步骤如下: 下载Gradle。可以从官网下载,或者使用腾讯的镜像下载地址进行下载。选择对应的版本进行下载。解压下载的压缩包,解压到指定的目录,例如解压到C盘根目录。配置环境变量。配置环境变量GRADLE_HOME&#xff0…

C++day3作业

完善对话框,点击登录对话框,如果账号和密码匹配,则弹出信息对话框,给出提示”登录成功“,提供一个Ok按钮,用户点击Ok后,关闭登录界面,跳转到其他界面 如果账号和密码不匹配&#xf…

数据分析讲课笔记01:数据分析概述

文章目录 零、学习目标一、本次课程概述二、数据分析的背景(一)进入大数据时代(二)数据分析的作用 三、什么是数据分析(一)数据分析的概念(二)数据分析的分类1、描述性数据分析2、探…

三菱PLC如何运用工业智能网关进行数据采集

在工业自动化领域,PLC(可编程逻辑控制器)作为一种关键的控制系统,发挥着越来越重要的作用。数据采集作为PLC应用的重要环节,关乎整个控制系统的稳定性和可靠性。而三菱PLC作为知名PLC的品牌,其数据采集技术…

代码随想录算法训练营第1天 | 704. 二分查找、27. 移除元素

数组理论基础 文章链接:https://programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 704.二分查找 题目链接:https://leetcode.cn/problems/binary-search/ (1)第一种写法:左闭右闭…

《剑指 Offer》专项突破版 - 面试题 8 : 和大于或等于 k 的最短子数组(C++ 实现)- 详解同向双指针(滑动窗口算法)

目录 前言 一、暴力求解 二、同向双指针(滑动窗口算法) 前言 题目链接:. - 力扣(LeetCode) 题目: 输入一个正整数组成的数组和一个正整数 k,请问数组中和大于或等于 k 的连续子数组的最短…

C++多线程打工人

为啥写这个,今天面试问到了~当时基于信号量写了一个单线程无锁队列的实现,但是面试官实际想要的是多线程条件变量实现的方式。 基本概念 生产者消费者模型是一种常见的并发设计模式,用于处理生产者(生成数据)和消费者&…

Rough.js:创建手绘、草图外观的图形

Rough.js 是一个小型的(<9kB gzipped)图形库&#xff0c;它可以让你以草图、手绘风格进行绘制。 该库定义了绘制直线、曲线、圆弧、多边形、圆和椭圆的基元。它还支持绘制 SVG 路径。 Rough.js 可以同时处理 Canvas 和 SVG。 安装 从npm安装&#xff1a; npm install --s…

【PDF密码】PDF文件为什么无法修改?为什么PDF文档不支持编辑?

pdf文件大家应该都经常接触&#xff0c;但是不知道大家会遇到这种情况&#xff1a;有些PDF文件打开之后无法编辑&#xff1f;是什么原因呢&#xff1f;今天我们来分析一下都是那些原因导致的。 首先我们可以考虑一下&#xff0c;PDF文件中的内容是否是图片&#xff0c;如果确认…

中国社科院大学与美国杜兰大学金融管理硕士项目——熬过寒冬,春日暖阳已不远

在金融领域&#xff0c;寒冬似乎成了无法避免的阶段。然而&#xff0c;对于那些坚守岗位的金融从业者来说&#xff0c;熬过寒冬并非无望。正如冬去春来&#xff0c;只要我们采取明智的策略&#xff0c;迈出坚定的步伐&#xff0c;春日的暖阳已在不远方照耀。社科院与美国杜兰大…

Vue2x的自定义指令和render函数使用自定义指令

在某些情况下&#xff0c;我们需要对底层DOM进行操作&#xff0c;而内置的指令不能满足需求&#xff0c;就需要自定义指令。一个自定义指令由一个包含类似组件的生命周期的钩子的对象来定义&#xff0c;钩子函数会接收到指令所绑定的元素作为参数。 定义指令 常用两种方式进行…

工作需要你的陪伴

初识CSDN 工欲善其事&#xff0c;必先利其器&#xff0c;要做好工作&#xff0c;先要使工具锋利&#xff0c;才能事半功倍。2019年开始学习编程的时候&#xff0c;总会遇到各种问题&#xff0c;都是英文看不懂&#xff0c;没办法只能百度搜索&#xff0c;当时搜索引擎排名靠前的…

只有金蝶用户,才懂金蝶BI方案的含金量

资深金蝶系统用户都看得明明白白&#xff0c;金蝶系统侧重于企业资源的计划和管理&#xff0c;而当前企业数字化运营决策不仅需要高效合理的流程管理&#xff0c;更需要一套完善的数据分析方案&#xff08;金蝶BI方案&#xff09;&#xff0c;无缝对接金蝶系统&#xff0c;智能…

Spring MVC 的RequestMapping注解

RequestMapping注解 使用说明 作用&#xff1a;用于建立请求URL和处理请求方法之间的对应关系。 出现位置&#xff1a; 类上&#xff1a; 请求 URL的第一级访问目录。此处不写的话&#xff0c;就相当于应用的根目录。写的话需要以/开头。它出现的目的是为了使我们的 URL 可以…

Python类型转换,数据类型转换函数大全 与 strip()函数介绍

Python类型转换&#xff0c;数据类型转换函数大全 虽然 Python 是弱类型编程语言&#xff0c;不需要像 Java 或 C 语言那样还要在使用变量前声明变量的类型&#xff0c;但在一些特定场景中&#xff0c;仍然需要用到类型转换。 比如说&#xff0c;我们想通过使用 print() 函数…