我正在尝试将泛型与协议混合在一起,我的xD非常困难
我在Android/Java项目中实现了某些架构,我正在尝试重写它以适应swift/iOS项目.但我发现了这个限制.
ProtocolA
protocol ProtocolA {
}
Run Code Online (Sandbox Code Playgroud)
ProtocolB
protocol ProtocolB : ProtocolA {
}
Run Code Online (Sandbox Code Playgroud)
ImplementProtocolA
class ImplementProtocolA <P : ProtocolA> {
let currentProtocol : P
init(currentProtocol : P) {
self.currentProtocol = currentProtocol
}
}
Run Code Online (Sandbox Code Playgroud)
ImplementProtocolB
class ImplementProtocolB : ImplementProtocolA<ProtocolB> {
}
Run Code Online (Sandbox Code Playgroud)
因此,当我尝试将ProtocolB设置为实现ProtocolA的具体类型时,我收到此错误:
不支持使用'ProtocolB'作为符合协议'ProtocolA'的具体类型
1这种"限制"有什么理由吗?
2是否有任何解决方法可以实现此功能?
3它会在某个时候得到支持吗?
- 更新 -
我认为同一问题的另一个变种是:
查看协议
protocol View {
}
protocol GetUserView : View {
func showProgress()
func hideProgress()
func showError(message:String)
func showUser(userDemo:UserDemo)
}
Run Code Online (Sandbox Code Playgroud)
演示者协议
protocol Presenter {
typealias V : View
}
class UserDemoPresenter : Presenter {
typealias V = GetUserView
}
Run Code Online (Sandbox Code Playgroud)
错误:
UserDemoPresenter.swift可能意图匹配'V'(又名'GetUserView')不符合'View'
那是什么??它符合!
即使我使用View而不是GetUserView,它也不会编译.
class UserDemoPresenter : Presenter {
typealias V = View
}
Run Code Online (Sandbox Code Playgroud)
UserDemoPresenter.swift可能意图匹配'V'(又名'View')不符合'View'
xxDD我真的不明白.
- 更新 -
根据Rob Napier提出的解决方案,问题并没有解决,相反,它只是延迟了.
当尝试定义对UserDemoPresenter的引用时,我需要指定泛型类型,因此我得到相同的错误:
private var presenter : UserDemoPresenter<GetUserView>
Run Code Online (Sandbox Code Playgroud)
不支持使用'GetUserView'作为符合协议'GetUserView'的具体类型
Rob*_*ier 62
限制的根本原因是Swift没有一流的元类型.最简单的例子是这不起作用:
func isEmpty(xs: Array) -> Bool {
return xs.count == 0
}
Run Code Online (Sandbox Code Playgroud)
从理论上讲,这段代码可以工作,如果确实如此,我可以制作很多其他类型(如Functor和Monad,今天真的无法在Swift中表达).但你不能.你需要帮助Swift将它钉到具体类型.通常我们使用泛型来做到这一点:
func isEmpty<T>(xs: [T]) -> Bool {
return xs.count == 0
}
Run Code Online (Sandbox Code Playgroud)
请注意,T这里完全是多余的.我没有理由表达它; 它从未使用过.但斯威夫特需要它,所以它可以把抽象Array变成具体的[T].在你的情况下也是如此.
这是一个具体类型(嗯,它是一个抽象类型,只要它被实例化并P填充就会变成具体类型):
class ImplementProtocolA<P : ProtocolA>
Run Code Online (Sandbox Code Playgroud)
这是一个完全抽象的类型,Swift没有任何规则可以变成具体类型:
class ImplementProtocolB : ImplementProtocolA<ProtocolB>
Run Code Online (Sandbox Code Playgroud)
你需要使它具体化.这将编译:
class ImplementProtocolB<T: ProtocolB> : ImplementProtocolA<T> {}
Run Code Online (Sandbox Code Playgroud)
并且:
class UserDemoPresenter<T: GetUserView> : Presenter {
typealias V = T
}
Run Code Online (Sandbox Code Playgroud)
仅仅因为你可能会在以后遇到这个问题:如果你要制作这些结构或final类,你的生活会更容易.混合协议,泛型和类多态性充满了非常尖锐的边缘.有时你很幸运,它不会编译.有时它会调用你不期望的东西.
您可能对A Little Respect for AnySequence感兴趣,其中详细介绍了一些相关问题.
private var presenter : UserDemoPresenter<GetUserView>
Run Code Online (Sandbox Code Playgroud)
这仍然是一种抽象类型.你的意思是:
final class Something<T: GetUserView> {
private var presenter: UserDemoPresenter<T>
}
Run Code Online (Sandbox Code Playgroud)
如果这会产生问题,则需要创建一个框.请参阅协议不符合自己?讨论如何键入 - 擦除,以便您可以保存抽象类型.但是你需要在具体类型中工作.你最终不能专注于协议.在大多数情况下,你最终必须专注于具体的事情.
| 归档时间: |
|
| 查看次数: |
20918 次 |
| 最近记录: |