基础概念

认识类的使用

image.png

类的定义

image.png

类的继承

image.png

类的成员修饰符

在TypeScript中,类的属性和方法支持三种修饰符: public、private、protected

  • public 修饰的是在任何地方可见、公有的属性或方法,默认编写的属性就是public的;
  • private 修饰的是仅在同一类中可见、私有的属性或方法;
  • protected 修饰的是仅在类自身及子类中可见、受保护的属性或方法; ```javascript class Person { private name: string = “”

    // 封装了两个方法, 通过方法来访问name getName() { return this.name }

    setName(newName) { this.name = newName } }

const p = new Person() console.log(p.getName()) p.setName(“why”)

  1. ```javascript
  2. // protected: 在类内部和子类中可以访问
  3. class Person {
  4. protected name: string = "123"
  5. }
  6. class Student extends Person {
  7. getName() {
  8. return this.name
  9. }
  10. }
  11. const stu = new Student()
  12. console.log(stu.getName())

只读属性 readonly

如果有一个属性我们不希望外界可以任意的修改,只希望确定值后直接使用,那么可以使用readonly:

  • 构造函数中可以给只读属性赋值进行初始化
  • readonly 就相当于类中的 const ```javascript class Person { // 1.只读属性是可以在构造器中赋值, 赋值之后就不可以修改 // 2.属性本身不能进行修改, 但是如果它是对象类型, 对象中的属性是可以修改 readonly name: string age?: number readonly friend?: Person constructor(name: string, friend?: Person) { this.name = name this.friend = friend } }

const p = new Person(“why”, new Person(“kobe”)) console.log(p.name) console.log(p.friend)

// 不可以直接修改friend // p.friend = new Person(“james”) if (p.friend) { p.friend.age = 30 }

// p.name = “123”

  1. <a name="GUKFr"></a>
  2. ## getters/setters
  3. 在前面一些私有属性我们是不能直接访问的,或者某些属性我们想要监听它的获取(getter)和设置(setter)的过程,<br />这个时候我们可以使用存取器。它不是函数,和 Java 中的不一样。新语言都有这种新的结构。
  4. ```javascript
  5. class Person {
  6. private _name: string
  7. constructor(name: string) {
  8. this._name = name
  9. }
  10. // 访问器setter/getter
  11. // setter
  12. set name(newName) {
  13. this._name = newName
  14. }
  15. // getter
  16. get name() { // 相当于有个属性 name
  17. return this._name
  18. }
  19. }
  20. const p = new Person("why")
  21. p.name = "coderwhy"
  22. console.log(p.name)

静态成员

前面我们在类中定义的成员和方法都属于对象级别的, 在开发中, 我们有时候也需要定义类级别的成员和方法。

  1. class Student {
  2. static time: string = "20:00"
  3. static attendClass() {
  4. console.log("去学习~")
  5. }
  6. }
  7. console.log(Student.time) // 直接通过类来访问
  8. Student.attendClass()

抽象类 abstract

我们知道,继承是多态使用的前提。在定义很多通用的调用接口时, 我们通常会让父类引用做形参。使用时,就会传入子类实例,通过多态让子类来实现具体的功能。

  1. function makeArea(shape: Shape) {
  2. return shape.getArea()
  3. }
  4. class Shape {
  5. // 计算图形面积
  6. getArea() {
  7. }
  8. }
  9. class Rectangle extends Shape {
  10. private width: number
  11. private height: number
  12. constructor(width: number, height: number) {
  13. super()
  14. this.width = width
  15. this.height = height
  16. }
  17. getArea() {
  18. return this.width * this.height
  19. }
  20. }
  21. class Circle extends Shape {
  22. private r: number
  23. constructor(r: number) {
  24. super()
  25. this.r = r
  26. }
  27. getArea() {
  28. return this.r * this.r * 3.14
  29. }
  30. }
  31. const rectangle = new Rectangle(20, 30)
  32. const circle = new Circle(10)
  33. console.log(makeArea(rectangle))
  34. console.log(makeArea(circle))

所以,父类本身可能并不需要对某些方法进行具体的实现。那如果给 makeAreg 函数直接传入父类实例就会造成错误。因此父类中定义的方法,,我们可以定义为抽象方法。

什么是 抽象方法? 在 TypeScript 中没有具体实现的方法(没有方法体),就是抽象方法。

  • 抽象方法,必须存在于 抽象类 中;
  • 抽象类是使用 abstract 声明的类;

抽象类有如下的特点:

  • 抽象类是不能被实例化(也就是不能通过new创建)
  • 抽象方法必须被子类实现,除非子类是个抽象类

    1. abstract class Shape {
    2. abstract getArea(): number
    3. }

    类的类型

    类本身也是可以作为一种数据类型: ```javascript class Person { name: string = “123” eating() {

    } }

// 类作为一个类型,字面类要和 Person 类结构一样 const p1: Person = { name: “why”, eating() {

} }

function printPerson(p: Person) { console.log(p.name) }

printPerson(new Person())

// 应用场景:直接将类本体当参数传入时,限制传参时乱写 printPerson({name: “kobe”, eating: function() {}}) ```