Can*_*ich 5 compiler-construction protocols swift
在阅读Swift 语言指南中关于Opaque Types的文档时,接近尾声的是片段:
// Error: Not enough information to infer C.
func makeProtocolContainer<T, C: Container>(item: T) -> C {
return [item]
}
Run Code Online (Sandbox Code Playgroud)
Container有一个关联类型 ,Item并且Array被扩展为符合Container。为什么编译器缺少信息来推断这是一个Array<T>?
另一个令人困惑的一点是,对于泛型函数,它们通常被编写为使用客户端代码指定的任何类型。那么不应该由客户端代码来决定是什么C而不是强加其返回类型的函数Array吗?
这就是我向我的团队解释不透明类型的方式。
您典型的通用函数(如您共享的代码段)可能看起来很清楚。为什么编译器不会将以下代码解释为返回Array<T>?
// Error: Not enough information to infer C.
func makeProtocolContainer<T, C: Container>(item: T) -> C {
return [item]
}
Run Code Online (Sandbox Code Playgroud)
错误的原因是因为如何C用作返回。当您将表单-> C中的某些内容视为通用返回时,您将该类型的定义留给caller。
因此,假设Array符合 as Container,那么您将能够执行以下操作:
let array: Array<Int> = makeProtocolContainer(Int(5))
Run Code Online (Sandbox Code Playgroud)
您的呼叫站点正在定义什么类型C。
但是如果您希望函数本身定义它呢?这就是不透明类型的用武之地。
在上面的示例中,该makeProtocolContainer函数应返回调用者可以定义的通用内容。但是函数本身定义了一个符合C的具体实现,这与返回泛型类型不同。
如果您希望函数本身指定类型,那么您只需要some在 Swift 中使用 new关键字对其进行修改即可。
func makeProtocolContainer<T>(item: T) -> some Container {
return [item]
}
Run Code Online (Sandbox Code Playgroud)
现在,该函数可以返回一个具体的类型。结果,调用者只能知道它是那种不透明类型,即使它们可能相等。
/// Error: Cannot convert value of type 'some Container' to specified type 'Array<String>'
let container: Array<String> = makeProtocolContainer(item: "A")
Run Code Online (Sandbox Code Playgroud)
您也不能使用泛型类型来保持不透明类型。
/// Error: Protocol 'Container' can only be used as a generic constraint because it has Self or associated type requirements
let container: Container = makeProtocolContainer(item: 5)
Run Code Online (Sandbox Code Playgroud)
但是您可以做的是允许类型推断或自己指定不透明类型。
let container = makeProtocolContainer(item: 5)
// Same as
let container: some Container = makeProtocolContainer(item: 5)
Run Code Online (Sandbox Code Playgroud)