MST

星途 面试题库

面试题:TypeScript中抽象类和接口在多态应用场景的选择

在一个大型的TypeScript项目中,有一个模块涉及多种图形(如圆形、矩形、三角形)的绘制和计算面积等操作。请分析在这种场景下,何时选择使用抽象类,何时选择使用接口来实现多态,并给出具体的代码示例说明你的选择原因。
30.7万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

抽象类

  1. 适用场景:当多个图形类有一些共同的属性或方法实现,并且这些图形类本质上属于同一类事物,需要有一个共同的基类来进行统一管理时,使用抽象类。例如,所有图形都可能有颜色这个属性,并且可能有一个共同的绘制到画布的基础实现逻辑。
  2. 代码示例
// 抽象图形类
abstract class Shape {
    color: string;
    constructor(color: string) {
        this.color = color;
    }
    // 抽象方法,子类必须实现
    abstract calculateArea(): number;
    // 具体实现的方法
    drawOnCanvas(): void {
        console.log(`Drawing ${this.constructor.name} with color ${this.color}`);
    }
}

// 圆形类继承自抽象图形类
class Circle extends Shape {
    radius: number;
    constructor(color: string, radius: number) {
        super(color);
        this.radius = radius;
    }
    calculateArea(): number {
        return Math.PI * this.radius * this.radius;
    }
}

// 矩形类继承自抽象图形类
class Rectangle extends Shape {
    width: number;
    height: number;
    constructor(color: string, width: number, height: number) {
        super(color);
        this.width = width;
        this.height = height;
    }
    calculateArea(): number {
        return this.width * this.height;
    }
}

// 使用示例
const circle = new Circle('red', 5);
circle.drawOnCanvas();
console.log(`Circle area: ${circle.calculateArea()}`);

const rectangle = new Rectangle('blue', 4, 6);
rectangle.drawOnCanvas();
console.log(`Rectangle area: ${rectangle.calculateArea()}`);

接口

  1. 适用场景:当只关注对象具有某些特定的行为(方法),而不关心这些对象的共同基类或属性时,使用接口。比如,不同类型的图形,它们的绘制逻辑和面积计算逻辑完全不同,只是都需要实现计算面积和绘制这两个行为。
  2. 代码示例
// 图形接口
interface ShapeInterface {
    calculateArea(): number;
    drawOnCanvas(): void;
}

// 圆形类实现图形接口
class Circle implements ShapeInterface {
    radius: number;
    constructor(radius: number) {
        this.radius = radius;
    }
    calculateArea(): number {
        return Math.PI * this.radius * this.radius;
    }
    drawOnCanvas(): void {
        console.log(`Drawing circle with radius ${this.radius}`);
    }
}

// 矩形类实现图形接口
class Rectangle implements ShapeInterface {
    width: number;
    height: number;
    constructor(width: number, height: number) {
        this.width = width;
        this.height = height;
    }
    calculateArea(): number {
        return this.width * this.height;
    }
    drawOnCanvas(): void {
        console.log(`Drawing rectangle with width ${this.width} and height ${this.height}`);
    }
}

// 使用示例
const circle = new Circle(5);
circle.drawOnCanvas();
console.log(`Circle area: ${circle.calculateArea()}`);

const rectangle = new Rectangle(4, 6);
rectangle.drawOnCanvas();
console.log(`Rectangle area: ${rectangle.calculateArea()}`);

选择原因总结:抽象类适合有共同属性和部分共同实现逻辑的场景,接口适合只关注特定行为实现,不关心类继承体系和共同属性的场景。在大型项目中,如果图形类有较多共同部分,抽象类能更好地复用代码和进行统一管理;如果图形类差异较大,只是需要有统一的行为规范,接口更合适。