给出没有任何功能的协议:
protocol NonFunkyProtocol {}
还有一个带有一些严重缺陷的协议:
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。
相反,我看到此错误:
在我的仿制药知识中,我很有可能会出现一个漏洞,我在哪里出错?
答案 0 :(得分:4)
问题在于,在这种情况下,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)
或者您需要通过将weeProp
设置为关联类型来将T
固定为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确实只是这一要求,那么您还应该问它要解决的是什么,而不仅仅是一个功能。当您可以直接使用WeeStruct
函数时,为什么要随身携带wee.funky
的所有协议包呢? FunkyProtocol上有协议扩展吗?如果您不能针对FunkyProtocol编写通用算法,则可能不应该是协议。