Skip to content

类的声明 & 实现

TS为成员属性和构造函数的参数添加了类型注解 run方法默认返回值是void

typescript
class Dog {
  constructor(name: string) {
    this.name = name
  }
  name: string
  run() {}
}

image.png

image.png

注:

无论是在ES还是TS中,类的成员属性都是实例属性(而不是原型属性),类的成员方法都是原型方法

打印类的原型,查看是否包含内部属性

typescript
console.log(Dog.prototype)

image.png

类的原型不包含内部属性,原型上只有 run 方法和 constructor 构造方法

创建一个实例,并且输出

typescript
class Dog {
  constructor(name: string) {
    this.name = name
  }
  name: string
  run() {}
}

console.log(Dog.prototype)

let dog = new Dog('wangcai')
console.log(dog)

image.png

可以看到,内部属性 name 只在实例上,而不在原型上

异同点:

  • 在TS实例的属性必须有初始值,或在构造函数中被初始化
  • 如删掉构造函数中对name的初始化,将提示错误
  • 如下代码所示:
typescript
class Dog {
  constructor(name: string) {
    // this.name = name;
  }
  name: string
  run() {}
}

console.log(Dog.prototype)

let dog = new Dog('wangcai')
console.log(dog)

image.png

处理:

typescript
// 初始值
{
  class Dog {
    constructor(name: string) {
      // this.name = name;
    }
    name: string = 'Dog'
    run() {}
  }

  console.log(Dog.prototype)

  let dog = new Dog('wangcai')
  console.log(dog)
}

// 可选属性
{
  class Dog {
    constructor(name: string) {
      // this.name = name;
    }
    name?: string
    run() {}
  }

  console.log(Dog.prototype)

  let dog = new Dog('wangcai')
  console.log(dog)
}

总结:只要内部属性有初始值,就不会报错

继承

类的继承使用了extends关键字 类的构造函数constructor中调用了super,代表父类实例 父类Dog的构造函数中有一个参数name,所以子类也必须要有具有此参数

typescript
// 继承
class Husky extends Dog {
  constructor(name: string, color: string) {
    super(name)
    this.color = color
  }
  color: string
}

成员修饰符

类的成员修饰符部分是TS对ES所做的扩展

公有成员-public

类的所有属性默认均为public,表示对所有人可见

typescript
class Dog {
  constructor(name: string) {
    this.name = name
  }
  public name: string
  run() {}
}

私有成员-private

私有成员,只能在类的本省调用,而不能被类的实例调用,也不能被子类调用

typescript
class Dog {
  constructor(name: string) {
    this.name = name
  }
  public name: string
  // name: string = 'dog'
  run() {}
  // 私有成员,只能在类的本省调用,而不能被类的实例调用,也不能被子类调用
  private pri() {}
}

let dog = new Dog('wangwang')
console.log(dog) // Dog {legs: 4, name: "wangwang"}
dog.pri()

image.png

私有成员也不能在子类中被调用

image.png

类的构造函数也可以被设置为私有成员,既不能被实例化也不能被继承了

typescript
// 类
class Dog {
  private constructor(name: string) {
    this.name = name
  }
  public name: string
  run() {}
  private pri() {}
}

let dog = new Dog('wangwang')

class Husky extends Dog {
  constructor(
    name: string,
    public color: string
  ) {
    super(name)
    this.color = color
  }
}

image.png

受保护成员-protected

受保护成员,只能在类或者子类访问与调用,而不能在类的实例访问

typescript
// 类
class Dog {
  constructor(name: string) {
    this.name = name
  }
  public name: string
  run() {}
  private pri() {}
  protected pro() {}
}

let dog = new Dog('wangwang')
dog.pro()

// 继承
class Husky extends Dog {
  constructor(
    name: string,
    public color: string
  ) {
    super(name)
    this.color = color
    this.pro()
  }
  // color: string;
}

image.png

构造函数也可以被声明为 protected,使这个类只能被继承,不能被实例化,相当于声明了一个基类

typescript
// 类
class Dog {
  protected constructor(name: string) {
    this.name = name
  }
  public name: string
  run() {}
  private pri() {}
  protected pro() {}
}

let dog = new Dog('wangwang')

// 继承
class Husky extends Dog {
  constructor(
    name: string,
    public color: string
  ) {
    super(name)
    this.color = color
    this.pro()
  }
  // color: string;
}

image.png

只读属性-protected

只读属性,这个属性不能被更改,而且不能被更改 和实例属性一样,类的只读属性必须被初始化

typescript
// 类
class Dog {
  constructor(name: string) {
    this.name = name
  }
  public name: string
  run() {}
  private pri() {}
  protected pro() {}
  readonly legs: number = 4
}

let dog = new Dog('wangwang')
console.log(dog) // Dog {legs: 4, name: "wangwang"}

静态成员-static

类的静态成员只能通过类名来调用,不能通过子类来调用 类的静态成员可以被继承

typescript
// 类
class Dog {
  constructor(name: string) {
    this.name = name
  }
  public name: string
  run() {}
  private pri() {}
  protected pro() {}
  readonly legs: number = 4
  static food: string = 'bones'
}

let dog = new Dog('wangwang')
console.log(dog.food)
console.log(Dog.food) // bones

// 继承
class Husky extends Dog {
  constructor(
    name: string,
    public color: string
  ) {
    super(name)
    this.color = color
    this.pro()
  }
}
console.log(Husky.food) // bones

image.png

构造函数的参数添加修饰符

除了类的成员可以添加修饰符外,构造函数的参数也可以添加修饰符 作用:将参数自动变成实例的属性,这样就可以省略在类中的定义

typescript
// 类
class Dog {
  constructor(name: string) {
    this.name = name
  }
  public name: string
  run() {}
  private pri() {}
  protected pro() {}
  readonly legs: number = 4
  static food: string = 'bones'
}

// 继承
class Husky extends Dog {
  constructor(
    name: string,
    public color: string
  ) {
    super(name)
    this.color = color
    this.pro()
  }
  color: string
}

image.png

抽象类的定义

抽象类只能被继承,不能被实例化 定义抽象类使用abstract关键字

typescript
abstract class Animal {}

let animal = new Animal()

image.png

抽象类的继承

继承抽象类,需要在子类中调用super方法

typescript
abstract class Animal {
  eat() {
    console.log('eat')
  }
}

class Dog extends Animal {
  constructor(name: string) {
    super()
    this.name = name
  }
  name: string
  run() {}
}
let dog = new Dog('wangwang')
console.log(dog.name)

抽象类实现方法复用

在抽象类中可以定义方法(可以有具体实现,也可以是抽象方法),从而实现复用 抽象类可以抽离事物的共性,有利于代码的复用和扩展

typescript
abstract class Animal {
  eat() {
    console.log('eat')
  }
  abstract sleep(): void
}

class Dog extends Animal {
  constructor(name: string) {
    super()
    this.name = name
  }
  name: string
  sleep() {
    console.log('Dog sleep')
  }
}
let dog = new Dog('wangwang')
dog.eat()
dog.sleep()

class Cat extends Animal {
  sleep() {
    console.log('Cat sleep')
  }
}
let cat = new Cat()
cat.eat()
cat.sleep()

抽象类实现多态

通过在父类中定义抽象方法,在不同子类中对该方法进行不同实现, 从而在运行时根据不同子类对象表现为不同状态

typescript
abstract class Animal {
  eat() {
    console.log('eat')
  }
  abstract sleep(): void
}

class Dog extends Animal {
  constructor(name: string) {
    super()
    this.name = name
  }
  name: string
  sleep() {
    console.log('Dog sleep')
  }
}
let dog = new Dog('wangwang')
dog.eat()
dog.sleep()

class Cat extends Animal {
  sleep() {
    console.log('Cat sleep')
  }
}
let cat = new Cat()
cat.eat()
cat.sleep()

let animal: Animal[] = [dog, cat]
animal.forEach((i) => {
  i.sleep()
})

this类型

类的成员方法可以直接返回一个this,方便实现链式调用,即Builder模式

typescript
class WorkFlow {
  step1() {
    return this
  }
  step2() {
    return this
  }
}
new WorkFlow().step1().step2()

使用this实现多态

this代表实例本身,继承时,子类实例即可表现多态(this既可以是父类,也可以是子类)

typescript
class WorkFlow {
  step1() {
    return this
  }
  step2() {
    return this
  }
}
new WorkFlow().step1().step2()

class Myflow extends WorkFlow {
  next() {
    return this
  }
}

new Myflow().next().step1().next().step2()

接口对类的约束作用

接口能够对类的成员属性和类型进行约束(且只能约束类的公有成员) 注意: 类必须实现接口中声明的全部属性和方法 类可以新增独有的属性和方法

typescript
interface Human {
  // new(name: string): void
  name: string
  eat(): void
}

// 类实现接口的时候,必须实现接口所有声明的属性
// 接口只能约束类的共有成员
// 接口不能约束构造函数
class Asion implements Human {
  constructor(name: string) {
    this.name = name
  }
  name: string
  eat() {}
  sleep() {}
}

image.png

接口继承

接口和类一样,可以相互继承,且一个接口可以继承多个接口 接口的继承特性可以将可重用部分进行抽离,也可以将多个接口合并成一个接口

typescript
interface Human {
  // new(name: string): void
  name: string
  eat(): void
}

// 类实现接口的时候,必须实现接口所有声明的属性
// 接口只能约束类的共有成员
// 接口不能约束构造函数
class Asion implements Human {
  constructor(name: string) {
    this.name = name
  }
  name: string
  eat() {}
  sleep() {}
}

// 接口继承
interface Man extends Human {
  run(): void
}

// 具有另外行为的接口
interface Child {
  cry(): void
}

// 多个接口组合使用
interface Boy extends Man, Child {}

// 属性与方法
let boy: Boy = {
  name: '',
  run() {},
  eat() {},
  cry() {},
}

接口继承类

接口除了可以继承接口外,还可以继承类,相当于将类成员全部抽象出来,仅有类的结构而没有具体实现 注意: 接口抽离类成员时,不仅抽离了公共成员,也抽离了私有成员和受保护成员

typescript
class Auto {
  state = 1
  // private state2 = 0;
}
interface AutoInterface extends Auto {}

class C implements AutoInterface {
  state = 1
}

image.png

image.png

image.png

typescript
class Auto {
  state = 1
  // private state2 = 0;
  protected state3 = 3
}
interface AutoInterface extends Auto {}

class C implements AutoInterface {
  state = 1
  // private state2 = 2;
  protected state3 = 3
}

class Bus extends Auto implements AutoInterface {}

学习笔记出自于梁宵老师课程

Layout Switch

Adjust the layout style of VitePress to adapt to different reading needs and screens.

Expand all
The sidebar and content area occupy the entire width of the screen.
Expand sidebar with adjustable values
Expand sidebar width and add a new slider for user to choose and customize their desired width of the maximum width of sidebar can go, but the content area width will remain the same.
Expand all with adjustable values
Expand sidebar width and add a new slider for user to choose and customize their desired width of the maximum width of sidebar can go, but the content area width will remain the same.
Original width
The original layout width of VitePress

Page Layout Max Width

Adjust the exact value of the page width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the page layout
A ranged slider for user to choose and customize their desired width of the maximum width of the page layout can go.

Content Layout Max Width

Adjust the exact value of the document content width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the content layout
A ranged slider for user to choose and customize their desired width of the maximum width of the content layout can go.

Spotlight

Highlight the line where the mouse is currently hovering in the content to optimize for users who may have reading and focusing difficulties.

ONOn
Turn on Spotlight.
OFFOff
Turn off Spotlight.