我正在尝试将泛型与协议混合在一起,而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的具体类型时,出现此错误:
不支持将“ ProtocolB”用作符合协议“ ProtocolA”的具体类型
1这种“限制”有什么理由吗?
2有什么解决方法可以实现此目标吗?
3是否会在某个时候提供支持?
我认为,同一问题的另一个变体是:
查看协议
protocol View { } protocol GetUserView : View { func showProgress() func hideProgress() func showError(message:String) func showUser(userDemo:UserDemo) }
Presenter protocols
protocol Presenter { typealias V : View } class UserDemoPresenter : Presenter { typealias V = GetUserView }
Error:
UserDemoPresenter.swift Possibly intended match ‘V’ (aka ‘GetUserView’) does not conform to ‘View’
What is that?? It conforms!
Even if I use View instead of GetUserView, it does not compile.
class UserDemoPresenter : Presenter { typealias V = View }
UserDemoPresenter.swift Possibly intended match ‘V’ (aka ‘View’) does not conform to ‘View’
xxDD I don’t get it, really.
使用罗布·纳皮尔(Rob Napier)提出的解决方案,问题并没有得到解决,而 只是被延迟了。
尝试定义对UserDemoPresenter的引用时,我需要指定 通用类型,因此会出现相同的错误:
private var presenter : UserDemoPresenter<GetUserView>
Using ‘GetUserView’ as a concrete type conforming to protocol ‘GetUserView’ is not supported
该限制的根本原因是Swift没有一流的元 类型。最简单的例子是,这不起作用:
func isEmpty(xs: Array) -> Bool { return xs.count == 0 }
从理论上讲,此代码可以工作,如果可以, 我可以创建很多其他类型的代码(例如Functor和Monad, 今天在Swift中实际上还无法表达它们)。但是你不能。您需要帮助Swift将其固定为 具体类型。通常,我们使用泛型来做到这一点:
func isEmpty<T>(xs: [T]) -> Bool { return xs.count == 0 }
注意,T这里完全多余。我没有理由要 表达它。它从未使用过。但是Swift需要它,因此它可以将摘要 Array变成具体的[T]。您的情况也是如此。
这是一个具体类型(嗯,它是一个抽象类型,在 实例化并P填充时会变成具体类型):
class ImplementProtocolA<P : ProtocolA>
This is a fully abstract type that Swift doesn’t have any rule to turn into a concrete type:
class ImplementProtocolB : ImplementProtocolA<ProtocolB>
You need to make it concrete. This will compile:
class ImplementProtocolB<T: ProtocolB> : ImplementProtocolA<T> {}
And also:
class UserDemoPresenter<T: GetUserView> : Presenter { typealias V = T }
只是因为您以后可能会遇到此问题:如果您要创建这些结构或final类,您的生活就会轻松得多。混合协议,泛型和类多态性充满了非常尖锐的边缘。有时您很幸运,而且它无法编译。有时它会发出您 意想不到的事情。
您可能对一点尊重 任何序列感兴趣,该序列详细介绍了一些相关问题。
This is still an abstract type. You mean:
final class Something<T: GetUserView> { private var presenter: UserDemoPresenter<T> }
如果这样会产生问题,则需要创建一个框。看到协议不符合自身?讨论如何进行类型擦除,以便 保留抽象类型。但是您需要处理具体类型。您最终不能专注于协议。在大多数情况下,您最终必须专注于具体的事情。