Swift - 继承协议关联类型擦除
Swift - Inherited Protocol Associated Type Erasure
我有 3 个协议和一个必须确定最专用协议的函数
protocol Super {}
protocol Sub1: Super { associatedtype T }
protocol Sub2: Super {}
func test(_ s: Super) { ... do stuff }
现在我已经用擦除类型试过了
class AnySub<E>: Sub1 {
typealias T = E
// ... standard type erasure init
}
有以下变化:
protocol Super {
func tryAsSub1() -> AnySub? {}
}
extension Sub1 {
func tryAsSub1() -> AnySub<T> { return AnySub<T>() }
}
extension Sub2 {
func tryAsSub1() -> AnySub { return nil }
}
func test(_ s: Super) {
if let sub1 = s.tryAsSub1() { ... do stuff for Sub1 }
else let sub2 = s as? Sub2 { ... do stuff for Sub2 }
}
但这显然行不通,因为我在 Super 和 Sub2 中没有任何通用参数。
有人知道我该如何解决这个问题吗?
由于Sub1
使用关联类型,您无法在运行时确定某个变量是否属于该类型。类型橡皮擦在一定程度上有所帮助,但是很难使用多种类型的橡皮擦。我的建议是为您需要处理的每种类型重载 test
方法。这也为您的代码增加了更多类型安全性。
func test<S: Sub1, T>(_ s: S) where S.T == T
func test(_ s: Sub2)
以上解决方案不适用于您拥有 Super
元素集合的场景,并且您需要根据实际类型执行一些操作。对于这种情况,一种可能的方法是在协议级别移动 test
方法,并在子协议中覆盖。
protocol Super {
func test()
}
protocol Sub1: Super { associatedtype T }
protocol Sub2: Super {}
extension Sub1 {
func test() { ... do stuff for Sub1 }
}
extension Sub2 {
func test() { ... do stuff for Sub2 }
}
缺点是一致性可以覆盖 test
,因此你会失去原来的实现。
我有 3 个协议和一个必须确定最专用协议的函数
protocol Super {}
protocol Sub1: Super { associatedtype T }
protocol Sub2: Super {}
func test(_ s: Super) { ... do stuff }
现在我已经用擦除类型试过了
class AnySub<E>: Sub1 {
typealias T = E
// ... standard type erasure init
}
有以下变化:
protocol Super {
func tryAsSub1() -> AnySub? {}
}
extension Sub1 {
func tryAsSub1() -> AnySub<T> { return AnySub<T>() }
}
extension Sub2 {
func tryAsSub1() -> AnySub { return nil }
}
func test(_ s: Super) {
if let sub1 = s.tryAsSub1() { ... do stuff for Sub1 }
else let sub2 = s as? Sub2 { ... do stuff for Sub2 }
}
但这显然行不通,因为我在 Super 和 Sub2 中没有任何通用参数。 有人知道我该如何解决这个问题吗?
由于Sub1
使用关联类型,您无法在运行时确定某个变量是否属于该类型。类型橡皮擦在一定程度上有所帮助,但是很难使用多种类型的橡皮擦。我的建议是为您需要处理的每种类型重载 test
方法。这也为您的代码增加了更多类型安全性。
func test<S: Sub1, T>(_ s: S) where S.T == T
func test(_ s: Sub2)
以上解决方案不适用于您拥有 Super
元素集合的场景,并且您需要根据实际类型执行一些操作。对于这种情况,一种可能的方法是在协议级别移动 test
方法,并在子协议中覆盖。
protocol Super {
func test()
}
protocol Sub1: Super { associatedtype T }
protocol Sub2: Super {}
extension Sub1 {
func test() { ... do stuff for Sub1 }
}
extension Sub2 {
func test() { ... do stuff for Sub2 }
}
缺点是一致性可以覆盖 test
,因此你会失去原来的实现。