Swift 尝试在闭包中使用泛型类型时出现意外编译器错误

Swift 尝试在闭包中使用泛型类型时出现意外编译器错误,swift,generics,Swift,Generics,给出一个没有任何恐惧的协议: protocol NonFunkyProtocol {} 还有一个带有严重恐惧的协议: protocol FunkyProtocol { func funky<T: NonFunkyProtocol>(_ closure: (T) -> Void) } 协议funky协议{ func funky(u闭包:(T)->Void) } 然后给出这个结构: struct WeeStruct: FunkyProtocol { let w

给出一个没有任何恐惧的协议:

protocol NonFunkyProtocol {}
还有一个带有严重恐惧的协议:

protocol FunkyProtocol {
    func funky<T: NonFunkyProtocol>(_ closure: (T) -> Void)
}
协议funky协议{
func funky(u闭包:(T)->Void)
}
然后给出这个结构:

struct WeeStruct: FunkyProtocol {
    let weeProp: NonFunkyProtocol
    
    func funky<T>(_ closure: (T) -> Void) where T: NonFunkyProtocol {
        closure(weeProp)
    }
}
struct-weeststruct:FunkyProtocol{
让我们哭泣吧:非未知的协议
func funky(u-闭包:(T)->Void)其中T:NonFunkyProtocol{
关闭(排水管)
}
}
我希望将其编译为
closure
中预期的参数类型为T,其中T符合非unknyprotocol,而
weeProp
为非unknyprotocol类型

相反,我看到了这个错误:


我很可能在我的泛型知识中有一个漏洞,我错在哪里了?

问题是
T
在这种情况下是“符合
非未知协议的某种类型”
weeProp
也是“符合
NonFunkyProtocol
”的东西,但是没有任何东西表明
weeProp
属于
T
类型

考虑以下情况:

extension Int: NonFunkyProtocol {}
extension String: NonFunkyProtocol {}
Int和String都符合

现在我用一个字符串构造一个WeeStruct:

let wee = WeeStruct(weeProp: "")
我用一个需要Int的函数调用
funky
(因为Int是一致类型,它可以是
T
):

因此,这将传递给闭包。这怎么行

因此,您需要要求闭包句柄any
NonFunkyProtocol
(我强烈怀疑这就是您的意思):

或者您需要通过使
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)
    }
}
协议funky协议{
关联类型T:非未知协议
func funky(u-闭包:(T)->Void)
}
结构WeeStruct:FunkyProtocol{
让我们哭泣吧
func funky(u-闭包:(T)->Void){
关闭(排水管)
}
}
不过,在添加关联类型之前,我会非常小心。这完全改变了FunkyProtocol的本质


如果FunkyProtocol真的只是这一个需求,那么您还应该询问它解决了什么,而不仅仅是一个函数。当您可以直接使用
wee.funky
功能时,为什么要传递
weestuct
及其所有协议行李?FunkyProtocol上有协议扩展吗?如果您不能编写针对FunkyProtocol的通用算法,那么它可能不应该是一个协议。

Lightbull矩!非常感谢,在这个特殊的例子中,你是对的,它不应该是一个协议,但它只是一个非常精炼的例子,试图围绕我在一个项目中遇到的问题来思考。
func funky(_ closure: (NonFunkyProtocol) -> Void)
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)
    }
}