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

如何解决Swift 不透明类型与协议 - 文档推断协议的函数不能嵌套

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

func protoFlip<T: Shape>(_ shape: T) -> Shape {
    if shape is Square {
        return shape
    }

    return FlippedShape(shape: shape)
}

然后声明:

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

然而,我写了这段代码

import Foundation

protocol P {
    associatedtype  AT
}


struct C: P {
    typealias AT = Int
}

func f<T: P>(_ t: T) -> T {
    t
}

func g() {
    f(f(C()))
}

g()

这会编译并运行……而且似乎让我可以嵌套这些调用

我误解了什么?文档想表达什么?

解决方法

你写的:

func f<T: P>(_ t: T) -> T

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

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

func protoFlip<T: Shape>(_ shape: T) -> Shape

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

这相当于:

func f<T: P>(_ t: T) -> P

(取一个 T 并返回一个存在的 P。)

如果你写了那个,你会发现你遇到了所描述的问题。您不能将 P 存在性传递到 f() 中,因为协议存在性不符合它们在 Swift 中的协议。 (这是由于静态方法和初始值设定项可以创建各种极端情况。而不是处理极端情况,今天的协议存在性只是不符合他们的协议。这可能会在未来发生变化的情况下可以允许,但目前不允许。)

不透明类型允许你写:

func f<T: P>(_ t: T) -> some P

返回一个符合 P 的具体(但不透明)类型,而不是返回 P 存在类型。系统将其跟踪为“当由 T 参数化时由 f 返回的类型”。它不等同于任何其他 some P,但它是具体的,在编译时已知,并且可以传入 f()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?