概述
面向对象思想:这也不是一朝一夕建立起来的
基础部分,学习类的时候,仅仅讨论新增的语法部分。
进阶的时候再讨论 抽象类 等等。
新增的类语法
- TS不允许动态的给对象添加属性,要求使用 属性列表(name: string) 来描述类中的属性!
- 属性列表也不存在于编译结果中!
- 防止在属性列表中声明属性却没在constructor中初始化的情况
- 配置:”strictPropertyInitialization”: true,//更加严格的方式检查属性是否进行了初始化
- 属性的初始化位置
- 构造函数中
- 属性默认值(可以在属性列表里设置默认值,也可以在构造函数的参数中使用默认值写法)
- 属性可以是可选的 ?: 也可以是只读的 readonly
- 我不希望类外面能访问到我的属性, JS怎么做? Symbol; TS呢?—>添加访问修饰符,有三种
- public:默认的访问修饰符,公开的,所有的代码均可访问
- private:私有的,只有在 类里面 可以访问
- protected:暂时不讲,todolist
- 语法糖:属性简写
- 如果某个属性,通过构造函数的参数传递,并且加上了修饰符(只读或者访问修饰符均可)且不做任何处理的赋值给该属性,则可以进行简写 ```typescript constructor(public name: string, readonly age: number){
}
```typescriptclass User {readonly id: number;//不能改变name: string;age: number;gender: '男' | '女' = '男';pid ?: string;//我不希望外面能访问到这两个属性, js怎么做? Symbol; TS呢?-->添加访问修饰符private publishNumber: number = 5;//每天最多发布的文章数量private curNumber: number = 0;//当前发布的文章数量,constructor(name: string, age: number, gender:'男'|'女', readonly what: string = 'whatever', pid?: string,){this.name = name;//报错,为啥。因为TS不允许动态的在对象中添加属性this.age = age;// this.gender = gender;// this.pid = pid;this.id = Math.random();console.log(this.curNumber);}publish(title: string){if(this.curNumber < this.publishNumber){console.log('发布一篇文章', title);this.curNumber++;}else{console.log('今日发布文章数量已上限.');}}}const u = new User('aa', 2, '女', );u.name = '2341';u.age = 324;// u.gender = '男';console.log(u);u.publish('title1');
访问器
比如:要对年龄的值要进行控制不能为负吧,不能大的离谱吧。
我们希望用函数来控制,这是最合适的。
Java中就是用 setName; getName ,JS也可以这样,这样需要调用函数
但是js有这个对应的语法糖,set name; get name;故ts也可以使用,也会在编译结果中出现,都是函数
注意:setter getter中用变量的时候不能出现 this.name 否则陷入无限递归,应该用this._name
这个就相当于是setter和getter,u.name会自动调用get name 而u.name = ‘wjw’;就会自动调用set name
练习:增加洗牌和发牌功能
用类改造扑克牌程序(在接口改造的基础上)
//发牌: 发完牌后,有四个card的数组,按斗地主来 17 17 17 3dealCards():[Card[], Card[], Card[], Card[]]{const res: [Card[], Card[], Card[], Card[]] = [[],[],[],[]];return res;}
上述看着挺烦的,那怎么改造呢?Card[]就是一叠牌Deck
import { Mark, Color } from "./enums";import { Card, Joker } from "./types"interface DealCardsResult {player1: Deckplayer2: Deckplayer3: Deckleft: 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({color: c,mark: m,getString() {return this.color + ' ' + this.mark;}} as Card);//类型断言}}let joker: Joker = {type: 'small',getString() {return 'joker'}}this.cards.push(joker);joker = {type: 'big',getString() {return 'JOKER';}}this.cards.push(joker);}//洗牌shuffle() {const len = this.cards.length;for (let i = 0; i < len; i++) {const targetIndex = this.getRandomNum(0, this.cards.length);[this.cards[i], this.cards[targetIndex]] = [this.cards[targetIndex], this.cards[i]];}}//发牌: 发完牌后,有四个card的数组,按斗地主来 17 17 17 3// dealCards(): [Card[], Card[], Card[], Card[]] {// const res: [Card[], Card[], Card[], Card[]] = [[], [], [], []];// return res;// }dealCards(): DealCardsResult {//这里可以直接使用这个问下下定义的类Deckconst player1: Deck = this.takeCards(17);const player2: Deck = this.takeCards(17);const player3: Deck = this.takeCards(17);const left: Deck = this.takeCards(3);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);//如果不断言,有可能是undefined,就会报错!}return new Deck(cards);//我给你的牌, 拿好}//无法取到最大值,最多是max-1private getRandomNum(min: number, max: number) {const sub = max - min;return Math.floor(Math.random() * sub + min);}print() {this.cards.forEach((card, i) => {let str = card.getString();console.log(str);if ((i + 1) % 4 === 0) {console.log('\n');}});}}
