vue3入门21 - typescript 类

284 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情

前言

我们在使用JavaScript开发时,使用函数和原型链继承可以创建复用性比较高的组件,但这并不符合面向对象的方式,面向对象是基于类的继承来实现的。ES6之后,JavaScript也能够基于类的面向对象方式进行开发。typescript在这方面也做了类型检查的支持,下面我们一起来看看吧。

  • 类(Class) : 定义了一切事物的抽象特点
  • 对象( Object) : 是类的实例,可以将类创建成具体的事物。
  • 面向对象(OOP)编程的三大特性: 封装、继承、多态
    • 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,
    • 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性。
    • 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。

封装

让我们先来封装一个类,在JavaScript中是这样定义的

// 封装
class Animal {
  constructor(name) {
    this.name = name;
  }
  run() {
    return `${this.name} is running`;
  }
}
const snake = new Animal('lily');

上面我们定义了一个类,并且进行了实例化,这里面还没有添加类型检查,我们如何把类型检查添加上呢?

class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  run() {
    return `${this.name} is running`;
  }
}
const snake = new Animal("lily");

我们对属性name做了类型检查,在typescript中,使用一个变量时需要对其做声明,或者标明是公共属性。这里定义的name: string就是在做变量声明,默认为公共属性,我们也可以改成下面的形式:

class Animal {
  constructor(public name) {
    this.name = name;
  }
  run() {
    return `${this.name} is running`;
  }
}
const snake = new Animal('lily');

在构造函数中声明name是公共属性,就不会报错了。

继承

有的时候我们需要对现有的类做一些扩展,比如我们上面声明的Animal类,我想声明一个Dog类,它具备Animal的特性,但又有自己的特性,我们就需要使用继承了。

class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  run() {
    return `${this.name} is running`;
  }
}

class Dog extends Animal {
  call() {
    console.log('I am dog');
  }
}

const dog = new Dog('lily');
dog.run();
dog.call()

公共,私有与受保护的修饰符

默认为public

我们刚刚提到了声明的name属性是公共属性,这个是默认属性,我们也可以明确标明哪些属性函数式公共的

class Animal {
  public name: string;
  public constructor(name: string) {
    this.name = name;
  }
  public run() {
    return `${this.name} is running`;
  }
}
const snake = new Animal("lily");

私有属性 private

当我们有些属性或者方法不想让外部访问到,包括派生和实例化,可以标记为private

class Animal {
  private name: string;
  constructor(name: string) {
    this.name = name;
  }
  run() {
    return `${this.name} is running`;
  }
}

class Dog extends Animal {
  constructor(name: string) {
    super(name);
  }
  call() {
    console.log(`I am ${this.name}`); // 派生类也会报错
  }
}

const dog = new Dog('lily');
dog.run();
dog.call();

const snake = new Animal('lily');
snake.name; // 这里会报错

image.png

派生可访问protected

如果我们不想让实例化后被访问,但是想让继承派生的类能访问怎么办呢?这个时候我们可以使用protected来声明:

class Animal {
  protected name: string;
  constructor(name: string) {
    this.name = name;
  }
  run() {
    return `${this.name} is running`;
  }
}

class Dog extends Animal {
  constructor(name: string) {
    super(name);
  }
  call() {
    console.log(`I am ${this.name}`); // 这里可以访问
  }
}

const dog = new Dog('lily');
dog.name;  // 这里会报错
dog.run();
dog.call();

const snake = new Animal('lily');
snake.name; // 这里会报错

总结

以上介绍的内容足够我们应对基本的开发需求,官方文档上还有很多内容,我们可以用到的时候再做讲解。