专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

前端编程:TypeScript是如何玩转接口和类的OOP特性?

ins518 2024-10-12 20:56:30 技术文章 13 ℃ 0 评论


编者按:

我们知道,接口和类是面向对象编程(OOP)的核心功能特性,为软件工程师们所喜闻乐见,并基于OO特性,软件工程师们能玩出各种创意,实现五花八门的功能软件。那么作为前端编程语言的JavaScript,其超集TypeScript又是如何为JavaScript全面点燃OO强类型语言特性的呢?

本篇文章分两部分来进行介绍。老规矩,为了方便学习和理解,还是以代码为主。若需要全面的学习TypeScript编程,请查阅专栏教程:《TypeScript编程:高效入门实战》

接口指定了实现该接口的任何类所期望的字段和函数的列表。要是某个类没有实现或拥有接口的所有字段和函数,那么该类并不算实现了相应接口

使用接口的主要好处是它允许人们以多态的方式使用不同类型的对象。这是因为任何实现接口的类至少具有这些字段和函数。

1. 扩展接口

假设我们有如下接口:

interface IPerson {
    name: string;
    age: number;
    breath(): void;
}


若我们想要创建更具体的接口,具有人(IPerson)的相同的属性,我们可以使用extends关键字进一步扩展此接口:

interface IManager extends IPerson {
    managerId: number;
    managePeople(people: IPerson[]): void;
}


此外,还可以扩展多个接口,在extends后用逗号分隔各个接口。形如:

class Engineer implements Developer, Coder, Scripter {
...
}


2. 类与接口

在接口中声明公共变量和方法类型,是为了定义其他typescript代码如何与之交互。比如:

interface ISampleClassInterface {
    sampleVariable: string;
    sampleMethod(): void;
    optionalVariable?: string;
}


下面创建一个实现接口的类:

class SampleClass implements ISampleClassInterface {
    public sampleVariable: string;
    private answerToLifeTheUniverseAndEverything: number;
    constructor() {
        this.sampleVariable = 'string value';
        this.answerToLifeTheUniverseAndEverything = 42;
    }
    public sampleMethod(): void {
        // do nothing
    }
    private answer(q: any): number {
        return this.answerToLifeTheUniverseAndEverything;
    }
}

注意:实现类必须拥有接口的所有成员,或说实体类必须实现接口所有成员。

该示例展示了如何创建接口ISampleClassInterface和实现该接口的类SampleClass。


3. 多态接口

使用接口的主要原因是为实现多态性,为开发人员在未来以自己的方式实现接口的方法提供了支持。

假设我们有一个接口和三个类:

interface Connector {
    doConnect(): boolean;
}


这是连接器接口。现在我们将为Wifi通信实现这个接口。代码如下:

export class WifiConnector implements Connector {
    public doConnect(): boolean {
        console.log("Connecting via wifi");
        console.log("Get password");
        console.log("Lease an IP for 24 hours");
        console.log("Connected");
        return true
    }
}


这里我们已经开发了名为wifiiconnector的具体类,它有自己的实现。现在是Connector类型。

现在我们正在创建具有Connector组件的系统。这叫做依赖注入。代码如下:

export class System {
    constructor(private connector: Connector) { //注入 Connector类型
        connector.doConnect()
    }
}


constructor(private connector: Connector) 这一行在这里非常重要。Connector是一个接口,必须具有doConnect()。由于Connector是一个接口,因此System类具有更大的灵活性。我们可以传递任何已经实现了Connector接口的类型。在未来开发人员获得更多的灵活性。例如,现在开发人员想添加蓝牙连接模块:

export class BluetoothConnector implements Connector {
    public doConnect(): boolean {
        console.log("Connecting via Bluetooth");
        console.log("Pair with PIN");
        console.log("Connected");
        return true
    }
}


如上所见,Wifi和Buletooth有自己的实现。他们有自己不同的联系方式。然而,因为两者都实现了类型Connector,它们现在都是Connector类型。这样我们就可以把它们中的任何一个作为构造函数参数传递给System类。这就叫做多态。类System现在不知道它是否存在Bluetooth/Wifi,甚至我们可以添加另外的通信模块,如Infrared(红外),Bluetooth5和任何实现Connector接口的类。

这叫做Duck typing(详见:https://en.wikipedia.org/wiki/Duck_typing)。 连接器类型现在是动态的,因为doConnect()只是一个占位符,开发人员根据自己的需要来为其提供实现。

如果在 constructor(private connector: WifiConnector)中WifiConnector是一个具体的类会发生什么?那么System类将只与WifiConnector紧密耦合了,而没有了其他可能。这里的接口通过多态性解决了我们的问题。

PS:

若希望系统学习TypeScript编程,请从这里开始:《TypeScript编程:高效入门实战》

本篇就写这些了,记得点个赞,分享出去吧。可以点击右上角的关注,以便随时来@牛旦IT课堂回看或阅读。谢谢啦,再见!

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表