Swift判断类型遵循带Self的协议报错,如何实现通用combine方法?
报错原因
Protocol can only be used as a generic constraint because it has Self or associated type requirements
这个报错是因为你定义的FooProtocol包含Self约束,属于带关联类型的协议(PAT),Swift 不允许直接将这类协议作为独立类型做运行时类型转换判断,仅能作为泛型约束使用。
实现方案
这里提供两种符合需求的实现方式,均支持传入任意类型参数,类型不遵循FooProtocol时自动返回nil:
方案1:泛型重载(最推荐)
利用Swift泛型重载的优先级规则,编译期自动匹配最合适的实现,无运行时类型转换开销,也没有强制解包风险:
protocol FooProtocol { static func combine(foo: Self, with element: Any) -> Self } // 优先匹配遵循FooProtocol的输入类型 func combine<T: FooProtocol>(foo: T, with element: Any) -> T? { return T.combine(foo: foo, with: element) } // 兜底匹配所有不遵循FooProtocol的输入类型 func combine<T>(foo: T, with element: Any) -> T? { return nil }
方案2:协议拆分+运行时判断
如果需要明确在运行时做类型校验,可以拆分出一层无Self/关联类型约束的标记协议,用于类型判断:
// 无约束的标记协议,仅用于运行时类型检查 protocol AnyFoo {} protocol FooProtocol: AnyFoo { static func combine(foo: Self, with element: Any) -> Self } func combine<T>(foo: T, with element: Any) -> T? { guard T.self is AnyFoo.Type else { return nil } func _innerCombine<U: FooProtocol>(_ target: U, _ element: Any) -> U { return U.combine(foo: target, with: element) } return _innerCombine(foo as! any FooProtocol, element) as? T }
内容的提问来源于stack exchange,提问作者Daisy the cat
相关产品推荐
相关产品推荐

