作者: sweetBoy_9126 | 来源:发表于2019-08-27 15:42 被阅读0次

类就是用来创造对象的东西。
类是高配版的接口。
接口是低配版的类。

语法

  1. 声明类
  2. 声明对象的非函数属性(下面的name和age)
  3. 声明对象的函数属性(下面的move)
  4. 使用 constructor(在我们实例化的时候就会调用constructor拿到里面的参数)
  5. 使用 this 代指当前对象(注意不要以为 this 永远都代指当前对象,JS 的 this 有更多功能,而且默认 this 为 window)
class HUman {
  name: string;
  age: number;
  constructor(name = 'lifa', age = 18) {
    this.name = name
    this.age = age
  }
  move(): void {
    console.log('我在动')
  }
}
let lifa = new HUman()
let jack = new HUman('jack')

// 接口只能定义类型不能定义初始值
interface Human2 {
  name: string;
  age: number;
  move(): void;
}
let lifa2: Human2 = {
  name: 'lifa2',
  age: 18,
  move() {
    console.log('我在动')
  }
}
let jack2: Human2 = {
  name: 'jack2',
  age: 18,
  move() {
    console.log('我在动')
  }
}

和接口相比较来说类的写法更加简单,在调用的时候只需要传入对应的参数值就可以,而且还可以初始化默认值和定义默认的方法,而接口必须每次使用的时候把参数值和参数都写一遍,不可以初始化默认值,只能定义方法的签名(参数类型和返回类型),至于这个方法怎么写它不支持。简而言之:接口只是帮你做了一个约束,不帮你实现任何功能,而class是可以实现具体的功能,也就是class是高配版的interface

  1. 声明类的静态属性(static:也就是这个类的属性)
    上面的代码中不管是age还是name还是constructor和move这些属性和方法都是实例对象的属性和方法,也就是我们的lifa和jack的属性和方法不是我们Human的属性和方法,如果我们要给Human添加属性和方法的话该怎么做那?
    正常的思维是直接Human.xxx = 1,但是ts会报错
    解决办法:通过static来声明就可以了
class HUman {
  static xxx = 1
  // 就等价于HUman.xxx = 1
}
console.log(HUman.xxx) //1

类继承

需要子类的constructor里调用super就相当于是调用超类的constructor,如果超类的constructor有参数那你调用super的时候就需要传入对应的参数

class Animal {
  body: string;
  kind: string;
  brith: string;
  constructor(kind: string) {
    this.kind = kind
    if(this.kind === '哺乳动物') {
      this.brith = '胎生'
    } else {
      this.brith = '卵生'
    }
  }
}
class HUman extends Animal{
  static xxx = 1
  name: string;
  age: number;
  constructor(name = 'lifa', age = 18) {
    super('哺乳动物')
    this.name = name
    this.age = age
  }
  move(): void {
    console.log('我在动')
  }
}
let lifa: HUman = new HUman()
console.log(lifa) // {kind: "哺乳动物", brith: "胎生", name: "lifa", age: 18}

修饰符

  • private
    私有属性(相当于一个升级版的局部变量),只能在当前class内部访问,外界访问不到
class HUman extends Animal{
  static xxx = 1
  name: string;
  private secret: string;
  age: number;
  constructor(name = 'lifa', age = 18) {
    super('哺乳动物')
    this.name = name
    this.age = age
  }
  move(): void {
    console.log('我在动')
  }
}
let lifa: HUman = new HUman()
console.log(lifa.age) //18
console.log(lifa.secret) //error 私有属性外界无法获取
  • public
    公有属性或方法,class外部也可以访问到,所有的属性或方法只要你不写private就默认是public

  • protected
    受保护的属性,只能在当前class和子级class里使用

class Animal {
  kind: string;
  // 在当前class里可以使用
  protected brith: string;
  constructor(kind: string) {
    this.kind = kind
    if(this.kind === '哺乳动物') {
      this.brith = '胎生'
    } else {
      this.brith = '卵生'
    }
  }
}
class HUman extends Animal{
  static xxx = 1
  name: string;
  private secret: string;
  age: number;
  constructor(name = 'lifa', age = 18) {
    super('哺乳动物')
    this.name = name
    this.age = age
  }
  say(): void {
    // 在子类里一样可以使用
    console.log(this.brith)
  }
}

访问器get和set

对于某些属性我们不想被人为随便的修改,我们需要对它进行约束,以上面的代码中的age为例,如果有人把我们的age修改为-1,上面的代码获取我们的age就会是-1,可年龄不可能小于0,所以这时候我们就需要使用get和set
(1). 我们需要对我们想要进行约束的属性变成私有属性

class HUman extends Animal{
  private age: number;
}

(2). 通过get和set来设置一个新的属性,get的时候直接返回这个age,set的时候对拿到的新的值进行判断,看是否满足条件,满足条件把这个新的值赋给age

class HUman extends Animal{
  private age: number;
  get age2() {
    return this.age
  }
  set age2(value) {
    if(value < 0) {
      this.age = 0
    } else {
      this.age = value
    }
  }
}
let lifa: HUman = new HUman()
lifa.age2 = -1
console.log(lifa.age2) // 0

上面的代码我们新加了一个age2显然有些多余,改进:
把我们需要隐藏的属性加一个下划线,然后get和set的改成你原来的

class HUman extends Animal{
  private _age: number;
  get age() {
    return this._age
  }
  set age(value) {
    if(value < 0) {
      this._age = 0
    } else {
      this._age = value
    }
  }
}
let lifa: HUman = new HUman()
lifa.age = -1
console.log(lifa.age)

总结:就是把我们真正用到的属性藏起来,在用户想要get的时候返回藏起来的属性,set的时候判断一下新的值是否符合要求,如果符合要求把它赋给那个藏起来的值,不符合要求就用一个符合要求的值代替它

抽象类

概述
也可以叫做「爸爸类」:专门当别的类的爸爸的类。
也可以叫做「没有写完的类」:只描述有什么方法,并没有完全实现这些方法。

  • 使用场景和特点详解
    1. 如果一个类里面有一个方法没有办法写实现(也就是说不能写具体的函数,只要声明参数类型和返回值类型,就和接口一样),这个方法前面就必须加一个抽象关键字(abstract)
    2. 如果方法是抽象的那么这个类的前面也要加一个抽象关键字
    具体代码:
abstract class Animal {
+  abstract makeNoice(): void
}

上面我们在Animal里添加了一个方法makeNoice意思是发出声音,而每个动物发出的声音不一样我们没法确定,所以只能声明这个方法而不能实现,也就是说只能是一个抽象的方法。
但是当我们这样添加了一个抽象的方法后,我们的子类HUman就会报错,因为HUman没有实现它的爸爸的方法makeNoice,所以我们需要让HUman实现以下这个方法

class HUman extends Animal{
+  makeNoice() {
    console.log('说人话')
  }
}

3. 抽象类是不能创建实例的,因为它没有实现这个方法
这个时候我们想给Animal创建一个实例,会发现它会报错

报错的原因是因为这个类没有写完,因为它里面的方法还没有实现,所以不能创建出对象

  1. 专门当别的类的爸爸的类
    因为Animal自己没有实现它的抽象方法,而它的儿子HUman可以实现,HUman实现了,HUman就可以创建一个实例,如果HUman也实现不了它就会再等它的儿子实现,所以它总是别的类的爸爸

5.抽象类也可以继承抽象类(可以当别的类的儿子)

abstract class X {
  abstract makeNoice(): void;
}
abstract class Animal extends X {
  kind: string;
  protected brith: string;
  constructor(kind: string) {
    super()
    this.kind = kind
    if(this.kind === '哺乳动物') {
      this.brith = '胎生'
    } else {
      this.brith = '卵生'
    }
  }
}

上面的Animal继承了X,但是因为Animal里没有实现X里的makeNoice所以也需要加一个abstract关键字,也就是说只要是继承了抽象类如果儿子没有实现爸爸的方法那么儿子一定是一个抽象类

相关文章

网友评论

      本文标题:

      本文链接:https://www.haomeiwen.com/subject/lxueectx.html