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

标签 swift generics

给定一个没有任何恐惧的协议(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。

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

error

我的泛型知识很可能存在漏洞,我哪里出错了?

最佳答案

问题在于,在这种情况下,T 是“某种符合 NonFunkyProtocol 的类型”。 weeProp 也是“符合 NonFunkyProtocol 的东西”,但没有任何内容表明 weePropT 类型。

考虑以下情况:

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/

相关文章:

c# - 为什么泛型类型在方法签名中出现两次?

Scala - 使用方法创建用户类型

Java 递归泛型和通配符

java - 推断泛型类中的参数类型,这些参数类型是所提供参数的嵌套泛型类型

ios - 从核心数据中的数组中获取具有关系的实体

ios - 有没有办法用数组构造一个 Firestore 字段(同名)并显示 TableView 中每个字段的每个数组元素

swift - 转换 ASCII 十进制

ios - swift 将第一响应者设置为文本字段,但没有光标可见

c# - 解析枚举跳过已过时

swift - 跟踪用户的位置,即使他们不使用它并不断将其更新到 Firebase