什么时候应该同时使用类和接口?

接口和类是面向对象编程(OOP)的基本组成部分。

TypeScript是一种面向对象的JavaScript语言,从ES6和更高版本开始,它支持OOP特性,如接口、类和封装。 但是什么时候我们应该同时使用接口、类或两者?如果您是一个新手或对使用接口和类感到困惑,这篇文章适合您。

在本文中,我将向您展示什么是接口和类,以及何时在TypeScript中使用它们中的一个或两个。

什么是TypeScript中的类?

在开始之前,我们需要知道什么是TypeScript类。在面向对象编程中,类是一个蓝图或模板,通过它我们可以创建具有特定属性和方法的对象。

Typescript为类型检查提供了额外的语法,并将代码转换为在任何平台和浏览器上运行的干净JavaScript。类涉及代码的所有阶段。将TypeScript代码转换为JavaScript文件后,您可以在最终文件中找到它们。

该类定义对象的模板,或者它是什么以及它做什么。让我们用属性和方法创建一个简单的类,这样我们就可以看到它的行为。

首先,我将通过以下代码行创建一个Developer类:

class Developer {
  name?: string; // string or undefined
  position?: string; // string or undefined
}
复制代码

我们用属性名称和位置来描述这个类。它们包含string和undefined等类型。

接下来,让我们使用new关键字通过Developer类创建一个对象:

const developer = new Developer();
developer.name // 输出 undefined
developer.position // 输出 undefined
复制代码

当我们调用developer.name时,它返回undefined,因为我们没有分配初始值。为了在TypeScript中创建具有值的对象,我们可以使用构造函数方法。构造函数方法用于初始化和创建对象。

现在,我们使用以下代码更新开发人员类:

class Developer {
  name: string; // only string
  position: string; // only string

  constructor(
      name: string, 
      position: string
      ) {
    this.name = name;
    this.position = position;
  }
}
复制代码

在上面的代码中,我们添加了构造函数方法来用值初始化属性。

现在,我们可以使用以下代码将名称设置为Gapur并定位为前端开发人员:

const developer = new Developer("Gapur", "Frontend Developer");
developer.name // 输出 Gapur
developer.position // 输出 Frontend Developer
复制代码

最后,正如我前面提到的,这个类有一些方法来说明对象应该如何操作。在这种情况下,任何开发人员都会开发应用程序,因此,开发人员类具有develope方法。

因此,开发人员对象可以执行开发操作:

class Developer {
  name: string;
  position: string;

  constructor(
      name: string, 
      position: string
      ) {
    this.name = name;
    this.position = position;
  }

  develop(): void {
    console.log('develop an app');
  }

}
复制代码

如果我们运行develope方法,它将执行以下console.log语句:

developer.develop() // 输出 develop an app
复制代码

什么是TypeScript中的接口?

接口是一种结构,在应用程序中起着契约的作用,或者是类所遵循的语法。接口也称为duck printing或subtyping。

接口只包含一个方法和字段声明,没有实现。我们不能用它来创造任何东西。实现接口的类必须具有所有字段和方法。因此,我们使用它们进行类型检查。

当TypeScript将所有代码转换为JavaScript时,该接口将从JavaScript文件中消失。因此,它在开发阶段是一个有用的工具。

我们应该为以下内容使用一个接口: 验证属性对象作为函数返回的参数对象的特定结构现在,让我们通过以下代码行声明接口:

  • 验证属性的特定结构
  • 对象作为参数
  • 从函数返回的对象

现在,让我们通过以下代码行声明接口:

interface InterfaceName {
  // variables;
  // methods;
}
复制代码

我们只能在接口体中包含变量和方法的声明。让我们为以前的开发人员类创建一个IDEDeveloper接口:

interface IDeveloper {
  name: string
  position: string
  develop: () => void
}

class Developer implements IDeveloper {
  name: string;
  position: string;

  constructor(name: string, position: string) {
    this.name = name;
    this.position = position;
  }

  develop(): void {
    console.log('develop an app');
  }
}
复制代码

在上面的代码中,我们的IDEDeveloper接口包含变量名称和位置。它还包括开发方法。因此,开发人员类实现了IDEDeveloper接口。因此,它必须定义两个变量和一个方法。

如果Developer类未实现任何变量,TypeScript将显示错误:

class Developer implements IDeveloper {
  // error Class 'Developer' incorrectly implements interface 'IDeveloper'.
  name: string;

  constructor(name: string, position: string) {
    this.name = name;
    this.position = position;
  }

  develop(): void {
    console.log('develop an app');
  }
}
复制代码

Interfaces vs classes

那么我们什么时候应该使用类,什么时候应该使用接口呢?

在开始之前,我想和大家分享一下强大的TypeScript静态属性,它允许我们使用类的字段和方法,而无需创建类的实例。

class Developer {
  static develop(app: { name: string, type: string }) {
    return { name: app.name, type: app.type };
  }
}
复制代码

现在,我们只需调用Developer.develope()方法,而无需实例化类:

Developer.develop({ name: 'whatsapp', type: 'mobile' })
// 输出: { "name": "whatsapp", "type": "mobile" } 
复制代码

此外,我们还可以在TypeScript中使用类进行类型检查。让我们使用以下代码创建一个App类:

class App {
  name: string;
  type: string;

  constructor(name: string, type: string) {
    this.name = name;
    this.type = type;
  }
}
复制代码

让我们修改Developer类:

class Developer {
  static develop(app: App) {
    return { name: app.name, type: app.type }; // 输出相同
  }
}
复制代码

现在,我将创建一个应用程序实例,并使用参数对象调用Developer.develope():

const app = new App('whatsapp', 'mobile');
Developer.develop(app);
// 输出: { "name": "whatsapp", "type": "mobile" } 
复制代码

Developer.develope(app)和Developer.develope({name:'whatsapp',type:'mobile'})输出相同的内容。这非常棒,但第二种方法更具可读性和灵活性。

另外,我们可以检查参数的类型。不幸的是,要这样做,我们需要创建一个对象。那么我们如何改进它呢?这就是interface的用武之地!

首先,我将App类更改为具有以下代码的接口:

interface App {
  name: string
  type: string
}

class Developer {
  static develop(app: App) {
    return { name: app.name, type: app.type }; // 输出相同的
  }
}
复制代码

在上面的代码中,我们没有更改Developer类的主体,也没有创建App的实例,但结果是一样的。在这种情况下,我们节省了大量的时间和代码输入。

结论

什么时候应该使用类和接口?如果要创建并传递类型检查类对象,则应使用TypeScript类。如果您需要在不创建对象的情况下工作,那么interface最适合您。

最终,我们打开了两个有用的方法:蓝图和契约。您可以同时使用这两个选项,也可以仅使用一个选项。这取决于你。

猜你喜欢

转载自juejin.im/post/7036669719457300494