美文网首页TypeScript
TypeScript(四)类与接口

TypeScript(四)类与接口

作者: 一蓑烟雨任平生_cui | 来源:发表于2019-10-30 16:16 被阅读0次

类实现接口

类类型接口是类遵循的某种约束和规则。

类可以通过关键字 implements 实现接口。

interface IPerson {
  name: string;
  eat(): void
}

class Person implements IPerson {
  // 如果构造函数参数中显式设置属性的访问控制符为public,则会默认初始化该属性
  constructor(public name: string) {}
  eat(): void {
    console.log( `${this.name} 吃饭` )
  }
}

const p1 = new Person('mike')
console.log(p1)

此外通过上文可知,一个类只能继承另一个类,但有时不同类之间却有一些共同的特性,这时可以把共有特性提取成接口,使用类去实现。

列举网上的一个案例:门是一个类,防盗门是门的子类。如果防盗门有一个报警器的功能,我们可以给防盗门添加一个报警方法。这时候如果有另一个类,车,也有报警器的功能,就可以考虑把报警器提取出来,作为一个接口,防盗门和车都去实现它:

interface Alarm {
  alarm(): void
}

class Door { }

class SecurityDoor extends Door implements Alarm {
  alarm() {
    console.log('SecurityDoor alarm')
  }
}

class Car implements Alarm {
  alarm() {
    console.log('Car alarm')
  }
}

一个类可以同时实现多个接口:

interface IPerson {
  name: string;
  eat(): void;
}

interface IPersonX {
  age: number;
  skill(): string;
}

class PersonX implements IPerson, IPersonX {
  name: string
  age: number
  constructor(name: string, age: number) { 
    this.name = name
    this.age = age
  }
  eat(): void {
    console.log( `${this.name} 吃饭` )
  }
  skill(): string {
    return `${this.name} age is ${this.age} sleep` 
  }
}

const p2 = new PersonX('nike', 12)

类的静态部分和实例部分

关于类需要明确的一点是,类有两部分,静态部分和实例部分。

通过以上方式定义的接口只会检查类实例的属性,对于类静态属性的检查需要单独定义接口。

首先通过下面例子思考一个问题:

interface PersonInterface {
  name: string
  age: number
  eat(): void
}

const person: PersonInterface = {
  name: 'mike',
  age: 12,
  eat() {
    console.log('food')
  }
}

class Person implements PersonInterface {
  name: string
  age: number
  constructor() {}
  eat() {
    console.log('food')
  }
}

接口PersonInterface很明显是一个对象类型的接口,为什么类实现接口时,类中存在constructor方法确不报错?那么类实现的接口究竟是对谁的约束?

事实上类实现的接口只是对类实例出来的对象的约束,只会对其实例属性进行检查。而TS中constructor方法则属于类的静态方法,即属于类的静态部分,对静态属性的约束需要额外定义接口。

TS中类的静态部分指的是这个类本身;
实例部分指的是类实例化出来的对象;

所以对类约束的接口需要通过以下方式定义:

interface IDogInterface {
  new (name: string, age: number)
  getName(): void
}

const Dog: IDogInterface = class {
  name: string
  age: number
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  static getName() {
    console.log('dog')
  }
}

再看下面例子:

interface PersonInterface {
  name: string
  age: number
  eat(): void
}

class Person implements PersonInterface {
  name: string
  age: number
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  eat() {
    console.log('food')
  }
}

const person = new Person(33, 'mike')

以上类Person实现接口PersonInterface,在类中我们定义了两个公有属性name、age,并对其类型进行了约束,注意:只是给类实例定义了两个属性name、age。
创建实例时,调用构造方法constructor,该函数接收的两个参数的类型是实际上是any类型,和公有属性name、age没有关系。创建实例的过程和js是一致的(首先创建一个对象,然后初始化该对象,再然后赋值给this,最后返回this)。

但是如果通过实例修改name的值,如果类型不一致则会报错。

person.name = 22 // Type '22' is not assignable to type 'string'

由此可以看出类实现的接口仅仅是对类实例的约束。

所以对一个类的实例部分和静态部分的约束需要定义两个接口,一个用来检查静态部分,一个用来检查实例部分。

// PersonConstructor 用来检查静态部分的
interface PersonConstructor {
  new(name: string, age: number): PersonInterface // 检查 constructor 并且创建的类必须是通过PersonInterface接口实现的
  typename: string              // 检查静态属性 typename 
  logname(): void               // 检查静态方法 logname 
}
// PersonInterface 用来检查实例部分的
interface PersonInterface {
  // new (name: string, age: number) // 静态方法的检查也不能写在这里 否则会报错
  log(): void                        // 定义实例方法 log
}

// 创建一个类,需要对类的静态部分(类本身)和实例部分都进行约束
const PersonClass: PersonConstructor = class implements PersonInterface {
  name: string
  age: number
  static typename = 'Person type' // 定义名为 typename 的静态属性
  static logname() {              // 定义名为 logname 的静态方法
    console.log(this.typename)
  }
  constructor(name: string, age: number) { // constructor 也是静态方法
    this.name = name
    this.age = age
  }
  log() { // log 是实例方法
    console.log(this.name, this.age)
  }
}

new(name: string, age: number): PersonInterface这里的意思是该接口对类的静态部分进行检查,并且我们创建的类必须是通过 PersonInterface接口实现的。

如果仅仅是这样定义的 new(name: string, age: number),那么满足该接口结构的类所实现的接口不会有限制。是不是有点绕。看例子说话:

interface IPersonConstructor {
  new(name: string, age: number);
  getName(): void
}

interface IPersonInterfaceX {
  eat(): void
}

interface IPersonInterfaceY {
  skill(): void
}

const PersonX: IPersonConstructor = class implements IPersonInterfaceX {
  static getName() {
    console.log('jack')
  }
  name: string
  age: number
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  eat() {
    console.log('food')
  }
}

const PersonY: IPersonConstructor = class implements IPersonInterfaceY {
  static getName() {
    console.log('jack')
  }
  name: string
  age: number
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  skill() {
    console.log('food')
  }
}

满足接口IPersonConstructor的类,其实现的类可以实现 IPersonInterfaceX 和 IPersonInterfaceY 接口。

一定要记住静态属性和方法的检查、实例属性和方法的检查是不同的 Interface

接口继承类

class Point {
  x: number
  y: number
}

interface Point3d extends Point {
  z: number
}

let point3d: Point3d = {x: 1, y: 2, z: 3}

接口也可以继承多个类:

class PointX {
  x: number
}

class PointY {
  y: number
}

interface Point3d extends PointX, PointY {
  z: number
}

let point3d: Point3d = {x: 1, y: 2, z: 3}

接口继承接口

接口可以继承一个或多个接口。查看接口继承以及混合类型TypeScript(二)接口

类继承

一个类可以继承另一个类,查看TypeScript(三)类

相关文章

  • TypeScript(四)类与接口

    类实现接口 类类型接口是类遵循的某种约束和规则。 类可以通过关键字 implements 实现接口。 此外通过上文...

  • TypeScript(四)类、接口

    认识类的使用 在早期的JavaScript开发中(ES5)我们需要通过函数和原型链来实现类和继承,从ES6开始,引...

  • TypeScript类与接口

    接口(Interfaces)可以用于对「对象的形状(Shape)」进行描述 类实现接口: 实现(implement...

  • TypeScript进阶(类与接口)

    类实现接口实现(implements)是面向对象中的一个重要概念。一般来讲,一个类只能继承自另一个类,有时候不同类...

  • Typescript接口、类

    一、接口 TypeScript的核心原则之一是对值所具有的结构进行类型检查。 它有时被称做“鸭式辨型法”或“结构性...

  • TypeScript interface extends cla

    TypeScript 中接口也可以继承类,并且接口可以继承类中的各个成员包括protect和private成员。假...

  • Typescript学习概要

    大致印象 TypeScript 增加了静态类型、类、模块、接口和类型注解. TypeScript 可用于开发大型的...

  • TypeScript(四)接口和类的区别

    接口只声明成员方法,不做实现。类声明并实现方法。 接口就是用于声明函数的,然后在类中去实现这些接口里的函数。 那么...

  • Typescript

    安装 Typescript 接口 interface 约束类型结构、Duck Typing 类型推论、联合类型、类...

  • TypeScript 学习笔记 之 接口与类

    接口 TS 中判断是否实现接口的核心原则是基于结构而不是基于名称的。即鸭子类型判断。 TS 中接口可以声明可选的接...

网友评论

    本文标题:TypeScript(四)类与接口

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