在这篇文章中,将用简单清晰的术语向你介绍 TypeScript 中的 mixins 概念,即使你是新手。

在 TypeScript 中拓展类

就像许多面向对象的编程语言一样,TypeScript 也有类。类是创建对象的蓝图——它们基本上用于封装对象中的数据。TypeScript 类可以这样定义:

class Subscribe {
  Remind() {
    console.log("Remember to subscribe to my channel");
  }
}

该类包含一个名为 remind 的函数,该函数在 DOM 的控制台中记录字符串。如果你有一个新的命名为 Youtube 的类

class Youtube {
  Begin() {
    console.log("Hi, Welcome to my channel!");
  }
  Ending() {
    console.log("Thank you for watching my video!");
  }
}

如果你想有一个类来扩展我们已经定义的两个类,以便在这个新类中访问它们,TypeScript 不允许这样做,所以它被标记为错误。你可以这样试试:

export class Recording extends Youtube, Subscribe{}

如果你尝试过这样做,你会看到当你把鼠标悬停在 IDE 上时,会告诉你 TypeScript 类只能扩展一个类的模糊行。当您第一次遇到这个问题时,您可能会想起 interfaces。

interfaces

在 TypeScript 中,类只能继承一个类,但接口可以继承多个类。使用 TypeScript 接口来解决我们的问题:

export class Recording {}
export interface Recording extends Youtube, Subscribe {}
const recording = new Recording();
recording.Remind();
recording.Ending();

我们创建一个接口,然后尝试查看是否可以访问已经定义的两个类中的函数。如果你在终端上运行 build:

tsc filename.ts
node filename.js

您将在构建的终端中看到一个错误,说明提醒和结束不是函数。这是因为 TypeScript 接口虽然可以扩展类,但却没有类的实现。这让我们回到了最初的问题,即在 TypeScript 的一个新类中不能访问多个类。

解决方案: Mixins

Mixins是一种在面向对象编程范式中实现重用组件的方法。对于我们前面的问题,可以是用一个mixins的辅助函数来解决,也就是在TypeScript的一个新类中扩展两个类。所以如果你是一个前端开发人员并使用SASS,你可能对mixins很熟悉。这是相同的概念,但用于扩展类。这个helper函数可以在TypeScript的官方文档中找到。

function applyMixins(derivedCtor: any, baseCtors: any[]) {
  baseCtors.forEach((baseCtor) => {
    Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {
      Object.defineProperty(
        derivedCtor.prototype,
        name,
        Object.getOwnPropertyDescriptor(baseCtor.prototype, name)
      );
    });
  });
}

现在你可以使用ApplyMixins函数来构建你的新类,像下面这样:

class Youtube {
 Begin(){
   console.log('Hi, Welcome to my channel!');
 }
 Ending(){
   console.log('Thank you for watching my video!');
 }
}
class Subscribe {
 Remind(){
   console.log('Remember to subscribe to my channel');
 }
}
// export class Recording extends Youtube, Subscribe{}
function applyMixins(derivedCtor: any, baseCtors: any[]) {
 baseCtors.forEach(baseCtor => {
   Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
     Object.defineProperty(derivedCtor.prototype, name, Object.getOwnPropertyDescriptor(baseCtor.prototype, name));
   });
 });
}
export class Recording {}
export interface Recording extends Youtube, Subscribe{}
applyMixins(Recording,[Youtube, Subscribe]);
const recording = new Recording
recording.Remind();
recording.Ending();

总结

本文简单介绍了TypeScript的Mixins概念,以及如何使用它实现多类继承。


看见了
876 声望16 粉丝

前端开发,略懂后台;