泛型类

概述

泛型类(Generic Classes)是 TypeScript 中一个强大的特性,它允许你创建可以处理多种数据类型的类。通过使用泛型,你可以编写更加灵活和可重用的代码,而不必为每种数据类型编写单独的类。

理论解释

什么是泛型类?

泛型类是一种类,它的某些部分(如属性、方法参数或返回值)可以在实例化时指定具体的数据类型。泛型类使用类型参数(Type Parameters)来表示这些可变的部分。

为什么使用泛型类?

  1. 代码复用:通过泛型类,你可以编写一次代码,然后在不同的上下文中使用它,而不必为每种数据类型编写单独的类。
  2. 类型安全:泛型类在编译时提供类型检查,确保你不会在运行时遇到类型错误。
  3. 灵活性:泛型类允许你编写更加灵活的代码,能够处理多种数据类型。

代码示例

基本泛型类

让我们从一个简单的泛型类开始。假设我们有一个 Box 类,它可以存储任何类型的值。

class Box<T> {
    private value: T;

    constructor(value: T) {
        this.value = value;
    }

    getValue(): T {
        return this.value;
    }

    setValue(value: T): void {
        this.value = value;
    }
}

// 使用 Box 类存储字符串
let stringBox = new Box<string>("Hello, TypeScript!");
console.log(stringBox.getValue()); // 输出: Hello, TypeScript!

// 使用 Box 类存储数字
let numberBox = new Box<number>(42);
console.log(numberBox.getValue()); // 输出: 42

在这个例子中,Box 类使用了一个类型参数 T,表示它可以存储任何类型的值。我们在实例化 Box 类时指定了具体的类型(如 string 或 number)。

泛型类的继承

泛型类也可以被继承,子类可以继承父类的类型参数,并添加自己的类型参数。

class AdvancedBox<T, U> extends Box<T> {
    private additionalValue: U;

    constructor(value: T, additionalValue: U) {
        super(value);
        this.additionalValue = additionalValue;
    }

    getAdditionalValue(): U {
        return this.additionalValue;
    }
}

// 使用 AdvancedBox 类
let advancedBox = new AdvancedBox<string, number>("Hello", 123);
console.log(advancedBox.getValue()); // 输出: Hello
console.log(advancedBox.getAdditionalValue()); // 输出: 123

在这个例子中,AdvancedBox 类继承了 Box 类,并添加了一个新的类型参数 U。

实践练习

练习 1:创建一个泛型栈类

创建一个泛型栈类 Stack<T>,它具有以下方法:

  • push(item: T): void:将一个元素压入栈顶。
  • pop(): T | undefined:从栈顶弹出一个元素。
  • peek(): T | undefined:查看栈顶元素,但不弹出。
  • isEmpty(): boolean:检查栈是否为空。
class Stack<T> {
    private items: T[] = [];

    push(item: T): void {
        this.items.push(item);
    }

    pop(): T | undefined {
        return this.items.pop();
    }

    peek(): T | undefined {
        return this.items[this.items.length - 1];
    }

    isEmpty(): boolean {
        return this.items.length === 0;
    }
}

// 使用 Stack 类
let numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
console.log(numberStack.peek()); // 输出: 2
console.log(numberStack.pop()); // 输出: 2
console.log(numberStack.isEmpty()); // 输出: false

练习 2:创建一个泛型队列类

创建一个泛型队列类 Queue<T>,它具有以下方法:

  • enqueue(item: T): void:将一个元素加入队列尾部。
  • dequeue(): T | undefined:从队列头部移除一个元素。
  • front(): T | undefined:查看队列头部的元素,但不移除。
  • isEmpty(): boolean:检查队列是否为空。
class Queue<T> {
    private items: T[] = [];

    enqueue(item: T): void {
        this.items.push(item);
    }

    dequeue(): T | undefined {
        return this.items.shift();
    }

    front(): T | undefined {
        return this.items[0];
    }

    isEmpty(): boolean {
        return this.items.length === 0;
    }
}

// 使用 Queue 类
let stringQueue = new Queue<string>();
stringQueue.enqueue("First");
stringQueue.enqueue("Second");
console.log(stringQueue.front()); // 输出: First
console.log(stringQueue.dequeue()); // 输出: First
console.log(stringQueue.isEmpty()); // 输出: false

总结

泛型类是 TypeScript 中一个非常强大的特性,它允许你编写灵活且可重用的代码。通过使用泛型类,你可以处理多种数据类型,而不必为每种数据类型编写单独的类。希望本教程能帮助你理解泛型类的基本概念,并通过实践练习掌握其使用方法。