Swift如何编写Optional扩展返回元素真实类型优化可选数组解包逻辑
解决方案
核心思路是通过泛型约束让编译器自动推导数组元素的真实子类类型,避免硬编码返回基类[A]丢失子类信息,两种实现方案均无需修改原有A、B、C类结构,完全适配存量项目。
方案1:保留计算属性写法(需添加辅助协议)
通过定义轻量辅助协议提取Optional的泛型类型,无需调整原有调用方式:
// 新增辅助协议,用于获取Optional的Wrapped类型 protocol OptionalProtocol { associatedtype Wrapped } extension Optional: OptionalProtocol {} // 统一扩展Optional extension Optional where Wrapped: Sequence, Wrapped.Element: OptionalProtocol { var vals: [Wrapped.Element.Wrapped] where Wrapped.Element.Wrapped: A { self?.compactMap { $0 } ?? [] } }
调用方式和原有逻辑完全一致,可直接访问子类独有属性:
var one: [B?]? = [B()] var two: [C?]? = [C(), nil] print(one.vals.count) // 输出1 print(two.vals.count) // 输出1 print(one.vals.first?.val ?? 0) // 正常输出B的val属性值1 print(two.vals.first?.num ?? 0) // 正常输出C的num属性值5
方案2:泛型方法写法(无需辅助协议)
如果不想新增全局协议,可以把计算属性调整为泛型方法,仅需在调用时加一对括号:
extension Optional { func vals<T: A>() -> [T] where Wrapped == [T?] { self?.compactMap { $0 } ?? [] } }
调用示例:
print(one.vals().count) // 输出1 print(two.vals().count) // 输出1 print(one.vals().first?.val ?? 0) // 输出1 print(two.vals().first?.num ?? 0) // 输出5
编译器会自动根据变量类型推导泛型T的真实类型,无需手动指定。
内容的提问来源于stack exchange,提问作者DNG
相关产品推荐
相关产品推荐

