给定一个没有任何恐惧的协议(protocol):
protocol NonFunkyProtocol {}
还有一个正在发生严重恐惧的协议(protocol):
protocol FunkyProtocol {
func funky<T: NonFunkyProtocol>(_ closure: (T) -> Void)
}
然后给出这个结构:
struct WeeStruct: FunkyProtocol {
let weeProp: NonFunkyProtocol
func funky<T>(_ closure: (T) -> Void) where T: NonFunkyProtocol {
closure(weeProp)
}
}
我希望它能够编译为 closure
中预期的参数类型为 T,其中 T 符合 NonFunkyProtocol,而 weeProp
的类型为 NonFunkyProtocol。
相反,我看到了这个错误:
我的泛型知识很可能存在漏洞,我哪里出错了?
最佳答案
问题在于,在这种情况下,T
是“某种符合 NonFunkyProtocol
的类型”。 weeProp
也是“符合 NonFunkyProtocol
的东西”,但没有任何内容表明 weeProp
是 T
类型。
考虑以下情况:
extension Int: NonFunkyProtocol {}
extension String: NonFunkyProtocol {}
Int 和 String 都符合。
现在我用字符串构造一个 WeeStruct:
let wee = WeeStruct(weeProp: "")
我用一个需要 Int 的函数调用 funky
(因为 Int 是一致类型,所以它可以是 T
):
wee.funky { (int: Int) -> Void in print(int + 1) }
因此这会将 ""
传递给闭包。这怎么行?
所以你要么需要闭包句柄any NonFunkyProtocol
(我强烈怀疑这就是你的意思):
func funky(_ closure: (NonFunkyProtocol) -> Void)
或者您需要通过使 T
成为关联类型来将 weeProp
固定为 T
:
protocol FunkyProtocol {
associatedtype T: NonFunkyProtocol
func funky(_ closure: (T) -> Void)
}
struct WeeStruct<T:NonFunkyProtocol>: FunkyProtocol {
let weeProp: T
func funky(_ closure: (T) -> Void) {
closure(weeProp)
}
}
不过,在添加关联类型之前我会非常小心。这完全改变了 FunkyProtocol 的性质。
如果 FunkyProtocol 确实只是这一要求,那么您还应该询问它正在解决什么问题,而不仅仅是一个函数。当您可以直接使用 wee.funky
函数时,为什么还要传递 WeeStruct
及其所有协议(protocol)包袱呢? FunkyProtocol 上有协议(protocol)扩展吗?如果您无法针对 FunkyProtocol 编写通用算法,那么它可能不应该成为一个协议(protocol)。
关于swift - 尝试在闭包中使用泛型类型时出现意外的编译器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55301662/