不支持使用某些协议作为符合其他协议的具体types
我正在尝试将generics和协议混合起来,而且我正在遇到xD
我在Android / Java项目中实现了一定的体系结构,我试图重写它以适应Swift / iOS项目。 但是我发现这个限制。
ProtocolA
protocol ProtocolA { }
ProtocolB
protocol ProtocolB : ProtocolA { }
ImplementProtocolA
class ImplementProtocolA <P : ProtocolA> { let currentProtocol : P init(currentProtocol : P) { self.currentProtocol = currentProtocol } }
ImplementProtocolB
class ImplementProtocolB : ImplementProtocolA<ProtocolB> { }
所以,当我尝试将ProtocolB设置为实现ProtocolA的具体types时,我得到这个错误:
不支持使用“ProtocolB”作为符合协议“ProtocolA”的具体types
1这个“限制”有什么理由吗?
2是否有任何解决方法来实现这个?
3在某些时候会得到支持吗?
– 更新 –
同样的问题的另一个变种,我想:
查看协议
protocol View { } protocol GetUserView : View { func showProgress() func hideProgress() func showError(message:String) func showUser(userDemo:UserDemo) }
演示者协议
protocol Presenter { typealias V : View } class UserDemoPresenter : Presenter { typealias V = GetUserView }
错误:
UserDemoPresenter.swift可能的匹配“V”(又名“GetUserView”)不符合“查看”
那是什么?? 它符合!
即使我使用View而不是GetUserView,它也不能编译。
class UserDemoPresenter : Presenter { typealias V = View }
UserDemoPresenter.swift可能预期的匹配“V”(aka'View')不符合'View'
xxDD我不明白,真的。
– 更新 –
Rob Napier提出的解决scheme不是固定的,而是延迟。
当试图定义对UserDemoPresenter的引用时,我需要指定genericstypes,所以我得到相同的错误:
private var presenter : UserDemoPresenter<GetUserView>
不支持使用“GetUserView”作为符合协议“GetUserView”的具体types
限制的根本原因是Swift没有一stream的元types。 最简单的例子是这不起作用:
func isEmpty(xs: Array) -> Bool { return xs.count == 0 }
从理论上讲,这个代码可以工作,如果这样做的话,还会有很多其他的types(比如Functor和Monad,现在还不能在Swift中expression)。 但是你不能。 你需要帮助Swift钉这个具体types。 通常我们用generics来做到这一点:
func isEmpty<T>(xs: [T]) -> Bool { return xs.count == 0 }
注意T
在这里完全是多余的。 我没有必要去expression它的理由。 它从来没有使用过。 但是Swift需要它,所以它可以把抽象的Array
变成具体的[T]
。 你的情况也是如此。
这是一个具体的types(好吧,它是一个抽象types,在实例化和P
被填充的时候,它将会变成一个具体的types):
class ImplementProtocolA<P : ProtocolA>
这是一个完全抽象的types,Swift没有任何规则可以变成具体types:
class ImplementProtocolB : ImplementProtocolA<ProtocolB>
你需要使它具体。 这将编译:
class ImplementProtocolB<T: ProtocolB> : ImplementProtocolA<T> {}
并且:
class UserDemoPresenter<T: GetUserView> : Presenter { typealias V = T }
以后可能会遇到这个问题:如果你做出这些结构或者final
堂课,你的生活会变得容易得多。 混合协议,generics和类多态性充满了非常尖锐的边缘。 有时你很幸运,它不会编译。 有时会叫你不期望的事情。
您可能会对AnySequence的一点尊重感兴趣,其中详述了一些相关的问题。
private var presenter : UserDemoPresenter<GetUserView>
这仍然是一个抽象types。 你意思是:
final class Something<T: GetUserView> { private var presenter: UserDemoPresenter<T> }
如果这造成问题,您需要创build一个框。 见协议不符合自己? 讨论你如何进行types擦除,以便可以保存抽象types。 但是你需要用具体的types来工作。 你最终不能专注于协议。 在大多数情况下,你最终必须专注于具体的事情。