接口和类是面向对象编程(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最适合您。
最终,我们打开了两个有用的方法:蓝图和契约。您可以同时使用这两个选项,也可以仅使用一个选项。这取决于你。