typescript学习回顾(四)

今天来分享下ts中的类,关于ts中的类的概念,面向对象的一种思想,以及类里面的一些属性成员,一些基础的用法,后面会有一个小练习。

基本概念

我的理解:类是编程语言中面向对象的一种思想,一个类是抽象事物的一个集合,比如人可以是一个类,类的实例对象具体到某一个人,所以这两者之间从抽象到具体。

面向对象思想

关于面向对象的一个思想的好处,可以让我们在开发的过程中,更易于维护我们的代码,以及我们的对象实例每个都是独立出来的,每次创建一个对象,都是NEW一个实例,每个实例之间互相不影响。面向对象用来编写模块化的代码也是非常的友好,而且公共类可以抽成接口用来继承,对于开发来说可以更加的清晰,逻辑更加的明确,同样对于灵活性和可扩展性也是有保障的。

  • 代码重用性
  • 代码可维护性

以前传统js类写法

es5
function User(userobj){this.name = userobj.name;this.age = userobj.age;this.sex = userobj.sex;this.phone = userobj.phone;this.address = userobj.address;
}const u = new User({name : 'kakarote',age : 18,sex : "男",phone : "1008611",address : "广东深圳宝安区"
});console.log(u)
es6
class User{constructor(userobj){this.name = userobj.name;this.age = userobj.age;this.sex = userobj.sex;this.phone = userobj.phone;this.address = userobj.address;}
}const u = new User({name: 'kakarote',age: 18,sex: "男",phone: "1008611",address: "广东深圳宝安区"
});console.log(u)

打印结果:

在这里插入图片描述

ts编写类

class User {constructor(name: string, age: number,sex:string,phone:string,address:string) {this.name = name;this.age = age;this.sex = sex;this.phone = phone;this.address = address;}
}

在这里插入图片描述

在ts中如果按照上面这种写法是会报错的,ts觉得这种写法不太好,如果我们写一个类,我们应该是清楚这个类里面到底有哪些属性的,创建属性里面的工作不允许放在构造函数里面写。因为如果可以添加的话就可能会造成很多有隐患的代码,最后可能都不清楚这个对象到底是有哪些属性,ts认为属性是不能添加的,必须提前限制好。

ts让我们使用属性列表来描述类里面的属性

列表直接写到class里面

class User {name: stringage: numbersex: stringphone: stringaddress: stringconstructor(name: string, age: number, sex: string, phone: string, address: string) {this.name = name;this.age = age;this.sex = sex;this.phone = phone;this.address = address;}
}

编译结果里面不会带这个属性列表

不能随意添加属性

比如下图我想给这个u实例添加一个id,这个在ts中是不允许的

在这里插入图片描述

更加严格的属性初始化

但是可能会有下面这种情况,我没有构造函数,但是我直接创建user实例也不会报错,但是这样user对象的每个属性都是undefined,就和类型不符合了

class User {name: stringage: numbersex: stringphone: stringaddress: string
}const u = new User();

或者说,我写了构造函数,但是有些在构造函数里没赋值,希望ts能够提示出来,这样怎么做呢

这里可以在tsconfig.json里面加上一个配置,这个属性为strictPropertyInitialization

{"compilerOptions": { //编译选项"strictPropertyInitialization": true //这样ts会对类里面的属性初始化进行严格校验},}

strictPropertyInitialization

这个属性它会监测

  • 构造函数中是否赋值
  • 是否存在属性默认值

设置默认值

这里一般性别都是男或者女,这里我希望能有个默认值

enum Sex{Male = "男",Female = '女'
}class User {name: stringage: numbersex: Sex = Sex.Male //设置默认值phone: stringaddress: string//这样可以少传递一个参数constructor(name: string, age: number phone: string, address: string) {this.name = name;this.age = age;this.phone = phone;this.address = address;}
}const u = new User(...具体参数);
u.sex = Sex.Female;

可选

类里面有些属性,我希望是可选的,那在ts中怎么写呢?

class User {name: stringage: numbersex: Sex = Sex.Male //设置默认值phone?: string //可以在:前面加个?这样就代表这个属性是可选的,可以传递也可以不传递
}

只读属性

在有些场景下,我们希望这个类的属性是只读属性,不能改的,比如说id属性,一般来说id都是自动生成的不可以改的,这里我们可以在属性前面加上readonly关键字

class User {readonly id:numbername: stringage: numbersex: Sex = Sex.Male //设置默认值phone?: string //可以在:前面加个?这样就代表这个属性是可选的,可以传递也可以不传递constructor(){///...//举例子this.id = new Date().getTime();}
}

使用访问修饰符

访问修饰符可以控制类中的某个成员的访问权限

  • public:默认的访问修饰符,公开的,所有代码均可以访问
  • private: 私有的,只有在类中可以访问
  • protected
class User {//...//设置私有的两个属性private _publishNumber: number = 3 //每天一共可以发布多少篇文章private _curNumber: number = 0; //当前文章发布数量publish(title: string) {if (this._curNumber < this._publishNumber) {console.log("发布了一篇文章" + title);this._curNumber++;} else {console.log("你今日发布的文章数量已达到上限")}}
}const u = new User("aa", 22);u.publish('文章1')
u.publish('文章2')
u.publish('文章3')
u.publish('文章4')

在这里插入图片描述

Tips:开发的原则,尽量少的暴露公共的属性,暴露出来的成员容易被其他开发者直接修改,容易造成很多隐患,所以一般都是暴露出一些需要用的函数和属性,一些不需要用的属性尽量私有化。

属性简写

如果某个属性,通过构造函数的参数传递,并且不做任何处理的赋值给该属性。可以进行简写

class User {sex: Sex = Sex.Male //设置默认值phone?: string //可以在:前面加个?这样就代表这个属性是可选的,可以传递也可以不传递constructor(public name: string, public age: number) {}
}const u = new User('kakarote',11);console.log(u)

前提是这里必须加上修饰符,不加修饰符是无效的

在这里插入图片描述

访问器

有些属性我们不希望直接对他进行赋值,以及直接进行读取,这样可能会存在一些问题,这里就需要用到访问器的知识

class User{//设置私有化_age变量constructor(public name: string, private _age: number) {}setAge(value: number) {if(value < 0){this._age = 0;}else if(value >= 200){this._age = 200;}else{this._age = value;}}getAge() {return Math.floor(this._age);}
}const u = new User("aa", 22);
console.log(u.getAge())
u.setAge(11)
console.log(u.getAge())

我们可以使用这种函数的形式,这样就可以实现一个访问器的效果,但是js的类里面给我们提供了get和set的一个关键字,这个关键字可以达到一样的效果,而且还可以让我们用传统的赋值和读取的写法。它的本质还是一个函数,有点类似Object.defineProperty的存取器

class User{//设置私有化_age变量constructor(public name: string, private _age: number) {}set age(value: number) {if(value < 0){this._age = 0;}else if(value >= 200){this._age = 200;}else{this._age = value;}}get age() {return Math.floor(this._age);}
}const u = new User("aa", 22);
console.log(u.age)
u.age = 11;
console.log(u.age)

在这里插入图片描述

这个完全是可以达到一样的效果的

小练习

我们上期typescript回顾二里面分享了扑克牌的功能,现在希望使用ts的类对它进行一个改造

1. 目标:创建一幅扑克牌(不包括大小王),打印该扑克牌,增加洗牌和发牌功能2. 使用枚举改造程序3. 使用模块化4. 用接口改造程序,加入大小王5. 用类改造程序
目录结构
  • src
    • deck.ts
    • enum.ts
    • index.ts
    • types.ts
enum.ts

定义枚举,形状以及标记

export enum Shape {heart = "♥",spade = "♠",club = "♣",diamond = "♦",
}export enum Mark {A = "A",two = "2",three = "3",four = "4",five = "5",six = "6",seven = "7",eight = "8",nine = "9",ten = "10",eleven = "J",twelve = "Q",king = "K"
}
type.ts

用来定义类型,普通牌的一个类型定义

import { Color, Mark } from "./enums";//一副牌是个Card数组
export type Deck = Card[];//定义每张牌
export interface Card {getString(): string
}//普通牌
export interface NormalCard extends Card {color: Color,mark: Mark,
}//大小王
export interface Joker extends Card {type: "big" | "small"
}
deck.ts

//用于定义具体的一个扑克牌游戏规则

import { Mark, Color } from "./enums";
import { Card, Joker } from "./types";//发牌对象,每个玩家发xx张牌
interface PublishResult {player1: Deck,player2: Deck,player3: Deck,left: Deck
}export class Deck {private cards: Card[] = [];constructor(cards?: Card[]) {if (cards) {this.cards = cards;} else {this.init();}}//初始化private init() {const marks = Object.values(Mark);const colors = Object.values(Color);for (const m of marks) {for (const c of colors) {this.cards.push({mark: m,color: c,getString() {return this.color + this.mark;}} as Card);}}let joker: Joker = {type: "small",getString() {return "jo"},}this.cards.push(joker);joker = {type: "big",getString() {return "Jo"},}this.cards.push(joker);}print() {let result = "\n";this.cards.forEach((card, i) => {result += card.getString() + "\t";if ((i + 1) % 6 === 0) {result += "\n";}});console.log(result)}/*** 洗牌*/shuffle() {//[x1,x2,x3,x4,x5,x6,x7]for (let i = 0; i < this.cards.length; i++) {const targetIndex = this.getRandom(0, this.cards.length);const temp = this.cards[i];this.cards[i] = this.cards[targetIndex];this.cards[targetIndex] = temp;}}// 发完牌后,得到的结果有4个card[]publish(): PublishResult {let player1: Deck, player2: Deck, player3: Deck, left: Deck;player1 = this.takeCards(17);player2 = this.takeCards(17);player3 = this.takeCards(17);left = new Deck(this.cards);return {player1,player2,player3,left};}private takeCards(n: number): Deck {const cards: Card[] = [];for (let i = 0; i < n; i++) {cards.push(this.cards.shift() as Card);}return new Deck(cards);}/*** 无法取到最大值* @param min * @param max * @returns */private getRandom(min: number, max: number) {const dec = max - min;return Math.floor(Math.random() * dec + min)}
}
index.ts

入口,引入扑克牌游戏

import { Deck } from "./deck";const deck = new Deck();
deck.shuffle();
console.log("===========洗牌之后===========")
deck.print();const result = deck.publish();
console.log("===========发牌之后===========");console.log("===========玩家1===========");
result.player1.print();console.log("===========玩家2===========");
result.player2.print();console.log("===========玩家3===========");
result.player3.print();console.log("===========玩家3===========");
result.player3.print();console.log("===========地主牌===========");
result.left.print();

在这里插入图片描述

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

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

相关文章

ChatTTS超真实自然的语音合成模型

项目介绍 ChatTTS是一款专为优化对话场景而生的语音生成模型&#xff0c;尤其匹配大型语言模型&#xff08;LLM&#xff09;的交互需求&#xff0c;以及生成对话式音频、视频旁白等应用场景&#xff0c;无缝覆盖中英文双语。 通过汲取约100,000小时的高质量中英语音数据进行深…

RedHat9 | podman容器

1、容器技术介绍 传统问题 应用程序和依赖需要一起安装在物理主机或虚拟机上的操作系统应用程序版本比当前操作系统安装的版本更低或更新两个应用程序可能需要某一软件的不同版本&#xff0c;彼此版本之间不兼容 解决方式 将应用程序打包并部署为容器容器是与系统的其他部分…

鸿蒙北向开发 ubuntu20.04 gn + ninja环境傻瓜式搭建闭坑指南

ninja跟gn都是比较时髦的东西,由歪果仁维护,如果走下载源码并编译这种流程的话需要走github跟google官网下载,国内的用网环境相信各位傻瓜都知道,github跟google这几年基本是属于连不上的状态,好在你看的鸿蒙项目跟国内的一些软件大厂已经帮你爬过梯子了,ninja工具跟gn工具已经…

一文弄懂梯度下降算法

1、引言 在上一篇文章中&#xff0c;我们介绍了如何使用线性回归和成本损失函数为房价数据找到最拟合的线。不过&#xff0c;我们也看到&#xff0c;测试多个截距值可能既繁琐又低效。在本文中&#xff0c;我们将深入探讨梯度下降算法&#xff0c;这是一种更加强大的技术&…

go~缓存设计配合singleFlight

一个缓存设计&#xff0c;配合go的singleFlight 最开始的设计如下 添加分布式缓存 上线后分布式缓存上涨的流量并不等于下游下降的流量&#xff0c;而是下游下降的流量 * 2&#xff5e;3 究其原因&#xff0c;就是采用了go的singleFlight&#xff0c;假定请求缓存时长10ms&a…

学校消防巡检二维码卡如何使用

为了加强和规范学校消防安全管理&#xff0c;预防和减少火灾危害&#xff0c;保障公共财产和教师、职工、学生的生命安全&#xff1b;传统的学校消防巡检都是纸质巡检记录会存在浪费纸张、信息滞后、容易造假、容易丢失、信息更新不及时。 通过凡尔码平台生成学校消防二维码巡…

揭秘:国产化系统加密

随着信息化时代的到来&#xff0c;数据安全已成为国家、企业和个人共同关注的焦点。政府系统国产化作为提高信息安全和自主可控能力的重要举措&#xff0c;正逐步得到广泛实施。在这一过程中&#xff0c;沙箱技术作为一种先进的安全机制&#xff0c;其在国产化系统加密效果方面…

系统设计中的垂直扩展和水平扩展,该如何选择?

在系统设计时&#xff0c;我们需要预估系统的容量&#xff0c;但是&#xff0c;随着系统流量的增大&#xff0c;我们会通过扩容来应对流量&#xff0c;常见的扩容方式是垂直扩展和水平扩展&#xff0c;因此&#xff0c;这本文章&#xff0c;我们将深入探讨这两种扩展策略的优缺…

项目管理中常见的6种度量指标,你知道吗?

在项目管理中&#xff0c;为了有效地监控和控制项目的进展、成本、质量等方面&#xff0c;我们通常会采用一系列的度量指标。这些度量指标不仅可以帮助项目经理了解项目的当前状态&#xff0c;还能预测未来的趋势&#xff0c;从而作出相应的决策。以下是六种常见的项目度量数据…

AI产品活跃用户排名出炉!文心一言APP国内第一,Kimi疯狂掉队

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/ 6月28日&#xff0c;极光大数据旗下月狐数据发布2024年5月中国生成式AI行业市场热点月度分析报告&#xff0c;披露了国内移动端主流生成式AI应用…

BFS:队列+树的宽搜

一、二叉树的层序遍历 . - 力扣&#xff08;LeetCode&#xff09; 该题的层序遍历和以往不同的是需要一层一层去遍历&#xff0c;每一次while循环都要知道在队列中节点的个数&#xff0c;然后用一个for循环将该层节点走完了再走下一层 class Solution { public:vector<vec…

AUTOSAR以太网之IPv4

系列文章目录 返回总目录 文章目录 系列文章目录一、IPv4报文格式二、主要函数1.IPv4_Init()2.IPv4_Receive()3.IPv4_Transmit() 一、IPv4报文格式 二、主要函数 1.IPv4_Init() 这个函数除了对模块配置进行初始化&#xff0c;如果有分包和组包使能&#xff0c;则会对一些相关…

桌面提醒工具哪个好?简单好用的便签提醒app推荐

在日常的生活和工作中&#xff0c;我们经常会遇到各种各样的事情&#xff0c;有时候可能会遗忘一些重要的事情。这个时候&#xff0c;一个简单好用的便签提醒工具就显得尤为重要了。那么&#xff0c;哪款桌面提醒工具比较好用呢&#xff1f;下面&#xff0c;就为大家推荐一款我…

ONNX模型利用CUDA加速如何正确配置好环境?

目前onnx可选的执行引擎非常多&#xff0c;覆盖了从cpu、gpu到npu&#xff0c;从Intel平台到AMD平台等。如下是onnxruntime所有的执行引擎。 [TensorrtExecutionProvider, CUDAExecutionProvider, MIGraphXExecutionProvider, ROCMExecutionProvider, OpenVINOExecutionProvide…

基于公有云部署wordpress

云平台选择 腾讯云 阿里云 华为云 项目部署 一、架构讲解 1.1、定义与组成 LNMP是Linux、Nginx、MySQL&#xff08;或MariaDB&#xff09;和PHP&#xff08;或Perl、Python&#xff09;的首字母缩写&#xff0c;代表在Linux系统下使用Nginx作为Web服务器&#xff0c;MySQL作为…

Mongodb安装与配置

Mongodb的下载 这里下载的是MongoDB 7.0.11版本的 首先进入官网&#xff1a;https://www.mongodb.com/ 点击完上面两步后&#xff0c;加载来到该页面&#xff0c;选择自己的版本、系统&#xff0c;是压缩包(zip)还是安装包(msi)。 下载好之后能&#xff0c;来到安装包哪里&a…

互联网直播/点播技术与平台创新应用:视频推拉流EasyDSS案例分析

随着互联网技术的快速发展&#xff0c;直播/点播平台已成为信息传播和娱乐的重要载体。特别是在电视购物领域&#xff0c;互联网直播/点播平台与技术的应用&#xff0c;不仅为用户带来了全新的购物体验&#xff0c;也为商家提供了更广阔的营销渠道。传统媒体再一次切实感受到了…

wavesummit2024发布飞桨3.0版本

今天网上看了wavesummit2024深度学习开发者大会,本来没有啥期待&#xff0c;结果发现飞桨竟然发布3.0版本了&#xff01; 以下是飞桨框架 3.x 的新特性&#xff1a; 动静统一自动并行&#xff1a; 为了降低大模型的编程难度&#xff0c;飞桨还优化了动静统一的半自动并行编程范…

陪诊小程序开发:寻找陪诊师更加快速,全程陪护!

陪诊行业是一个新兴行业&#xff0c;在当下市场中具有较大的发展前景。对于无法陪家人看病或者对医院不熟悉的人来说&#xff0c;陪诊师成为了刚需&#xff01;目前随着社会的发展&#xff0c;人们的生活节奏不断加快&#xff0c;陪诊市场的需求量也在不断增加&#xff0c;发展…

荣耀终端发布首个端侧AI反诈检测技术,助力用户防范网络诈骗

在今日盛大开幕的2024年上海世界移动通信大会上&#xff0c;荣耀终端以卓越的创新实力引领行业潮流&#xff0c;率先发布了手机行业中首个端侧AI反诈检测技术。该技术旨在为用户提供更加安全、可靠的网络通信体验&#xff0c;助力防范日益猖獗的网络诈骗行为。 AI-321 | 专注全…