You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift:如何遍历泛型类实例组成的数组

解决Swift泛型类数组存储与遍历问题

这个问题我之前也碰到过,核心原因是Swift泛型的不变性在搞鬼——MyClass<Int>和MyClass<Double>是完全独立的类型,既不能直接塞进同一个无类型标注的数组,也没法强制转成MyClass<Any>(强制转换会直接崩溃)。下面给你两种靠谱的解决方案:

方案一:使用协议统一类型

这是最常用的方式,通过定义一个包含目标方法的协议,让泛型类遵守协议,就能用协议类型作为数组的元素类型了:

// 定义协议,包含需要调用的方法
protocol IdentifiableType {
    func whoAreYou()
}

// 让泛型类遵守协议
class MyClass<T>: IdentifiableType {
    func whoAreYou() {
        print("I am \(T.self)")
    }
}

// 创建实例并存储到协议类型数组中
let a = MyClass<Int>()
let b = MyClass<Double>()

let objects: [IdentifiableType] = [a, b]
for object in objects {
    object.whoAreYou()
}

运行后会输出:

I am Int
I am Double

方案二:类型擦除(AnyMyClass)

如果不想用协议,或者需要处理更复杂的泛型逻辑,可以创建一个类型擦除的包装类,把不同泛型参数的MyClass实例统一包装起来:

class MyClass<T> {
    func whoAreYou() {
        print("I am \(T.self)")
    }
}

// 类型擦除的包装类
class AnyMyClass {
    private let _invokeWhoAreYou: () -> Void
    
    // 初始化时捕获原实例的方法
    init<T>(_ instance: MyClass<T>) {
        _invokeWhoAreYou = instance.whoAreYou
    }
    
    // 对外暴露统一的调用方法
    func whoAreYou() {
        _invokeWhoAreYou()
    }
}

// 包装实例并存入数组
let a = MyClass<Int>()
let b = MyClass<Double>()

let objects: [AnyMyClass] = [AnyMyClass(a), AnyMyClass(b)]
for object in objects {
    object.whoAreYou()
}

这个方案同样能得到正确的输出结果。

为什么你的原代码不行?

简单来说:

  • Swift的泛型是不变的,MyClass<Int>和MyClass<Any>没有继承关系,强制转换as! MyClass<Any>会在运行时触发崩溃;
  • 直接写[a, b]时,编译器无法推断出这两个实例的共同超类型,所以会报错。

内容的提问来源于stack exchange,提问作者ukim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:28:33