繁体   English   中英

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 }
}

不利之处在于,conformers可以覆盖test ,因此您将失去原始的实现。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM