Swift 不透明类型与协议 - 文档推断协议的 func 不能嵌套

Phi*_*den 5 swift opaque-types

在阅读 Apple 关于不透明类型的Swift 编程语言指南时,有一段我不明白。该指南讨论了不透明类型和协议之间的差异,并指出不能嵌套返回协议类型的调用。他们使用这个代码片段,其中 Shape 是一个协议:

\n
func protoFlip<T: Shape>(_ shape: T) -> Shape {\n    if shape is Square {\n        return shape\n    }\n\n    return FlippedShape(shape: shape)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

然后它指出:

\n
\n

这种方法的另一个问题是形状变换不嵌套。翻转三角形的结果是 Shape 类型的值,并且 protoFlip( :) 函数采用符合 Shape 协议的某种类型的参数。但是,协议类型的值不符合该协议;protoFlip( :) 返回的值不符合 Shape。这意味着像 protoFlip(protoFlip(smallTriange)) 这样应用多个变换的代码是无效的,因为翻转的形状不是 protoFlip(_:) 的有效参数\xe2\x80\x99t。

\n
\n

但是,我写了这段代码:

\n
import Foundation\n\nprotocol P {\n    associatedtype  AT\n}\n\n\nstruct C: P {\n    typealias AT = Int\n}\n\nfunc f<T: P>(_ t: T) -> T {\n    t\n}\n\nfunc g() {\n    f(f(C()))\n}\n\ng()\n
Run Code Online (Sandbox Code Playgroud)\n

这编译并运行......并且似乎让我嵌套这些调用。

\n

我理解错了什么?文档试图说明什么?

\n

Rob*_*ier 5

你写了这个:

func f<T: P>(_ t: T) -> T
Run Code Online (Sandbox Code Playgroud)

这需要并返回相同的类型。

那不是问题。问题是这个例子:

func protoFlip<T: Shape>(_ shape: T) -> Shape
Run Code Online (Sandbox Code Playgroud)

这需要一个 T 并返回一个 Shape 存在主义。

这相当于:

func f<T: P>(_ t: T) -> P
Run Code Online (Sandbox Code Playgroud)

(接受 T 并返回 P 存在主义。)

如果您这样写,您会发现您已经描述了问题。您无法将 P 存在性传递给f(),因为协议存在性不符合 Swift 中的协议。(这是由于静态方法和初始化程序可能会创建各种极端情况。今天的协议存在性不是处理极端情况,而是不符合其协议。在未来的情况下,这可能会改变可以允许,但目前不允许。)

不透明类型允许您编写:

func f<T: P>(_ t: T) -> some P
Run Code Online (Sandbox Code Playgroud)

这不是返回一个 P 存在主义,而是返回一个具体的符合 P 的它并不等同于任何其他some P,但它是具体的,在编译时已知,并且可以传递到f().

  • 斯威夫特进化:https://forums.swift.org/t/se-0309-unlock-existential-types-for-all-protocols/47515 (2认同)
  • @CRDave 是的。请参阅 Sajjon 包含的链接。“解锁所有协议的存在。” 具体请查看类型擦除包装器部分。我上次看到的时候,这本书的不透明类型部分目前正在根据编译器的最新更改进行修改。 (2认同)