不支持使用某些协议作为符合其他协议的具体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来工作。 你最终不能专注于协议。 在大多数情况下,你最终必须专注于具体的事情。