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
相关产品推荐
相关产品推荐

