概述

面向对象思想:这也不是一朝一夕建立起来的

基础部分,学习类的时候,仅仅讨论新增的语法部分。
进阶的时候再讨论 抽象类 等等。

新增的类语法

  1. TS不允许动态的给对象添加属性,要求使用 属性列表(name: string) 来描述类中的属性!
    1. 属性列表也不存在于编译结果中!
  2. 防止在属性列表中声明属性却没在constructor中初始化的情况
    1. 配置:”strictPropertyInitialization”: true,//更加严格的方式检查属性是否进行了初始化
  3. 属性的初始化位置
    1. 构造函数中
    2. 属性默认值(可以在属性列表里设置默认值,也可以在构造函数的参数中使用默认值写法)
  4. 属性可以是可选的 ?: 也可以是只读的 readonly
  5. 我不希望类外面能访问到我的属性, JS怎么做? Symbol; TS呢?—>添加访问修饰符,有三种
    1. public:默认的访问修饰符,公开的,所有的代码均可访问
    2. private:私有的,只有在 类里面 可以访问
    3. protected:暂时不讲,todolist
  6. 语法糖:属性简写
    1. 如果某个属性,通过构造函数的参数传递,并且加上了修饰符(只读或者访问修饰符均可)且不做任何处理的赋值给该属性,则可以进行简写 ```typescript constructor(public name: string, readonly age: number){

}

  1. ```typescript
  2. class User {
  3. readonly id: number;//不能改变
  4. name: string;
  5. age: number;
  6. gender: '男' | '女' = '男';
  7. pid ?: string;
  8. //我不希望外面能访问到这两个属性, js怎么做? Symbol; TS呢?-->添加访问修饰符
  9. private publishNumber: number = 5;//每天最多发布的文章数量
  10. private curNumber: number = 0;//当前发布的文章数量,
  11. constructor(name: string, age: number, gender:'男'|'女', readonly what: string = 'whatever', pid?: string,){
  12. this.name = name;//报错,为啥。因为TS不允许动态的在对象中添加属性
  13. this.age = age;
  14. // this.gender = gender;
  15. // this.pid = pid;
  16. this.id = Math.random();
  17. console.log(this.curNumber);
  18. }
  19. publish(title: string){
  20. if(this.curNumber < this.publishNumber){
  21. console.log('发布一篇文章', title);
  22. this.curNumber++;
  23. }else{
  24. console.log('今日发布文章数量已上限.');
  25. }
  26. }
  27. }
  28. const u = new User('aa', 2, '女', );
  29. u.name = '2341';
  30. u.age = 324;
  31. // u.gender = '男';
  32. console.log(u);
  33. 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

练习:增加洗牌和发牌功能

用类改造扑克牌程序(在接口改造的基础上)

  1. //发牌: 发完牌后,有四个card的数组,按斗地主来 17 17 17 3
  2. dealCards():[Card[], Card[], Card[], Card[]]{
  3. const res: [Card[], Card[], Card[], Card[]] = [[],[],[],[]];
  4. return res;
  5. }

上述看着挺烦的,那怎么改造呢?Card[]就是一叠牌Deck

  1. import { Mark, Color } from "./enums";
  2. import { Card, Joker } from "./types"
  3. interface DealCardsResult {
  4. player1: Deck
  5. player2: Deck
  6. player3: Deck
  7. left: Deck
  8. }
  9. export class Deck {
  10. private cards: Card[] = [];
  11. constructor(cards?: Card[]) {
  12. if (cards) {
  13. this.cards = cards;
  14. } else {
  15. this.init();//你不传我就自己初始化
  16. }
  17. }
  18. //因为我不需要让外面知道我的初始化
  19. private init() {
  20. const marks = Object.values(Mark);
  21. const colors = Object.values(Color);
  22. for (const m of marks) {
  23. for (const c of colors) {
  24. this.cards.push({
  25. color: c,
  26. mark: m,
  27. getString() {
  28. return this.color + ' ' + this.mark;
  29. }
  30. } as Card);//类型断言
  31. }
  32. }
  33. let joker: Joker = {
  34. type: 'small',
  35. getString() {
  36. return 'joker'
  37. }
  38. }
  39. this.cards.push(joker);
  40. joker = {
  41. type: 'big',
  42. getString() {
  43. return 'JOKER';
  44. }
  45. }
  46. this.cards.push(joker);
  47. }
  48. //洗牌
  49. shuffle() {
  50. const len = this.cards.length;
  51. for (let i = 0; i < len; i++) {
  52. const targetIndex = this.getRandomNum(0, this.cards.length);
  53. [this.cards[i], this.cards[targetIndex]] = [this.cards[targetIndex], this.cards[i]];
  54. }
  55. }
  56. //发牌: 发完牌后,有四个card的数组,按斗地主来 17 17 17 3
  57. // dealCards(): [Card[], Card[], Card[], Card[]] {
  58. // const res: [Card[], Card[], Card[], Card[]] = [[], [], [], []];
  59. // return res;
  60. // }
  61. dealCards(): DealCardsResult {//这里可以直接使用这个问下下定义的类Deck
  62. const player1: Deck = this.takeCards(17);
  63. const player2: Deck = this.takeCards(17);
  64. const player3: Deck = this.takeCards(17);
  65. const left: Deck = this.takeCards(3);
  66. return { player1, player2, player3, left };
  67. }
  68. private takeCards(n: number): Deck {
  69. const cards: Card[] = [];
  70. for (let i = 0; i < n; i++) {
  71. cards.push(this.cards.shift() as Card);//如果不断言,有可能是undefined,就会报错!
  72. }
  73. return new Deck(cards);//我给你的牌, 拿好
  74. }
  75. //无法取到最大值,最多是max-1
  76. private getRandomNum(min: number, max: number) {
  77. const sub = max - min;
  78. return Math.floor(Math.random() * sub + min);
  79. }
  80. print() {
  81. this.cards.forEach((card, i) => {
  82. let str = card.getString();
  83. console.log(str);
  84. if ((i + 1) % 4 === 0) {
  85. console.log('\n');
  86. }
  87. });
  88. }
  89. }