深入讲解接口在代码规范与多态实现的应用

后端 潘老师 4天前 7 ℃ (0) 扫码查看

今天,咱们就通过实际案例,深入了解一下接口的概念、组成、使用方式,还有它和抽象类之间的区别。

一、接口

接口本质上是一份代码协定,它定义了一种新的类型,规定了一组属性和方法的标准,但并不涉及这些属性和方法具体该如何实现。打个比方,接口就像是一份设计蓝图,只告诉大家房子应该有哪些房间(属性)和功能(方法),至于每个房间怎么装修、功能怎么实现,那是具体施工(类的实现)时要考虑的事。

举个例子,在图形绘制系统里,我们定义一个Shape接口:

interface Shape {
    calculateArea(): number;
}

这个Shape接口规定,所有实现它的类都必须有一个calculateArea方法,用来计算图形的面积。这样一来,不管是圆形、矩形还是其他形状,只要实现了这个接口,就必须按照这个规范来提供计算面积的功能。

二、接口的构成

接口主要由属性和方法两部分组成,它们各自有着不同的作用和表现形式。

(一)属性声明

属性在接口里可以以字段、gettersetter或者它们的组合形式存在。以描述网页元素样式的Style接口为例:

interface Style {
    color: string;
}

这里的color属性就是一个字段,它要求实现Style接口的类必须包含一个string类型的color属性。

属性也能用gettersetter来定义,下面这两种方式效果是一样的:

// 方式一:字段形式
interface Style {
    color: string;
}

// 方式二:getter/setter形式
interface Style {
    get color(): string;
    set color(x: string);
}

在类实现的时候,对应方式如下:

// 方式一对应的类实现
class StyledElement1 implements Style {
    color: string = 'blue';
}

// 方式二对应的类实现
class StyledElement2 implements Style {
    private _color: string = 'green';
    get color(): string {
        return this._color;
    }
    set color(x: string) {
        this._color = x;
    }
}

(二)方法声明

继续拿前面的图形绘制系统来说,我们给Shape接口添加一个draw方法,用来描述图形的绘制行为:

interface Shape {
    calculateArea(): number;
    draw(): void;
}

这个draw方法声明就像是给实现Shape接口的类下了一个“任务”,要求它们必须提供绘制图形的具体逻辑。

三、接口的实现

当一个类实现接口时,就好比是一个施工队按照设计蓝图来盖房子,必须把蓝图上要求的所有“设施”(属性和方法)都具体实现出来。

以矩形为例,它要实现Shape接口:

class Rectangle implements Shape {
    private width: number;
    private height: number;

    constructor(width: number, height: number) {
        this.width = width;
        this.height = height;
    }

    calculateArea(): number {
        return this.width * this.height;
    }

    draw(): void {
        console.log(`Drawing a rectangle with width ${this.width} and height ${this.height}`);
    }
}

在这个例子里,Rectangle类实现了Shape接口里的calculateAreadraw方法,这样我们就能通过Shape接口来操作Rectangle类的实例,实现多态性。也就是说,我们可以把不同形状(如矩形、圆形等,只要实现了Shape接口)的对象都当作Shape类型来处理,调用它们各自实现的calculateAreadraw方法,而不用关心具体是哪个形状的对象。

四、接口继承

接口之间也可以有继承关系。一个接口继承另一个接口后,会拥有被继承接口的所有属性和方法,同时还能添加自己特有的内容。

还是在图形绘制系统中,我们定义一个ColoredShape接口,让它继承自Shape接口,并增加一个颜色属性:

interface Shape {
    calculateArea(): number;
    draw(): void;
}

interface ColoredShape extends Shape {
    color: string;
}

那么实现ColoredShape接口的类,不仅要实现Shape接口的所有方法,还要实现ColoredShape接口新增的color属性。比如ColoredRectangle类:

class ColoredRectangle implements ColoredShape {
    private width: number;
    private height: number;
    color: string;

    constructor(width: number, height: number, color: string) {
        this.width = width;
        this.height = height;
        this.color = color;
    }

    calculateArea(): number {
        return this.width * this.height;
    }

    draw(): void {
        console.log(`Drawing a ${this.color} rectangle with width ${this.width} and height ${this.height}`);
    }
}

五、抽象类与接口

抽象类和接口都不能直接创建实例,但它们在很多方面有着明显的区别。

(一)继承与实现的差别

一个类只能继承一个抽象类,就好像一个孩子只有一个亲生父母;而一个类可以实现一个或多个接口,这就好比一个人可以同时拥有多种身份。例如:

// 抽象类
abstract class Animal {
    abstract makeSound(): void;
}

// 接口
interface Flyable {
    fly(): void;
}

class Bird extends Animal implements Flyable {
    makeSound(): void {
        console.log('Chirp');
    }
    fly(): void {
        console.log('Flying');
    }
}

这里Bird类继承了Animal抽象类,同时实现了Flyable接口。

(二)成员的不同之处

接口里面不能有静态代码块和静态方法,而抽象类是可以有的。抽象类里可以有方法的具体实现,而接口完全是抽象的,所有方法都没有实现。另外,抽象类可以有构造函数,接口则不允许有构造函数。

// 抽象类
abstract class AbstractClass {
    static staticMethod() {
        console.log('This is a static method in abstract class');
    }

    abstract abstractMethod(): void;

    constructor() {
        console.log('Abstract class constructor');
    }
}

// 接口
interface MyInterface {
    // 不能有静态代码块、静态方法和构造函数
    someMethod(): void;
}

总之,接口在编程过程中意义重大,它让代码的组织更加有序,扩展性更强,通过多态性实现了代码的高效复用。希望通过这篇文章,大家对接口有了更透彻的理解,在编程时能更好地发挥接口的优势。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/back/17657.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】