Mar*_*eIV 3 generics existential-type swift
通常在讨论诸如 之类的事情时some,它们指的是返回类型。这个问题具体是关于在参数列表中使用anyor 的some。
例如,在 的 Swift 文档中String,您有这个初始化程序...
init<T>(_ value: T, radix: Int = 10, uppercase: Bool = false)
where T : BinaryInteger
Run Code Online (Sandbox Code Playgroud)
在 Swift 5.6 中,他们引入了any关键字,让我们更轻松地处理存在类型。通过这一更改,我知道理论上您可以像这样重写上面的内容......
init(_ value: any BinaryInteger, radix: Int = 10, uppercase: Bool = false)
Run Code Online (Sandbox Code Playgroud)
当然还有这个基于some关键字的版本,也可以...
init(_ value: some BinaryInteger, radix: Int = 10, uppercase: Bool = false)
Run Code Online (Sandbox Code Playgroud)
我的问题是……哪一个最有意义?使用存在类型而不是像这样的泛型有缺点吗?版本怎么样some?我最初认为是的,通用版本是最好的,因为编译器可以在编译时确定传递给它的内容,但话又说回来,存在any甚至some版本也是如此,因为如果不传递它,它就不会编译aBinaryInteger并且我不太确定如何编写测试来检查这一点。
传递协议类型的值时P给 Swift 中的方法时,当前可以使用 4 种可能的拼写:
func f<T: P>(_ value: T)(“通用的”)func f(_ value: some P)(“不透明参数”)func f(_ value: P)(“‘裸露’存在主义”)func f(_ value: any P)(“\'显式\'存在主义”)在这些拼写中,(1) 和(2) 是同义词,目前,(3) 和(4) 是同义词。使用(1)和(2)之间没有区别,(3)和(4)之间目前*没有区别;但在 (1)/(2) 和 (3)/(4) 之间,有。
\nf<T: P>(_: T)是采用保证符合协议的具体类型参数的传统方法TP。这种获取参数的方式:\nT,以便您可以执行操作T,以便您可以对其自身执行操作T在编译时已知,并且编译器知道值的大小和布局,并且可以适当地设置堆栈/寄存器;它可以将提供给它的任何参数直接传递给该方法Self- 或associatedtype要求的协议类型进行调用some Protocol正是通用版本我将避免重复提案的内容,但简介部分阐明了对此语法的渴望,以此来简化拼写通用参数的复杂性f(_: P)是采用保证符合协议的存在类型参数的传统方法P。这种获取参数的方式:\ntype(of:)P并且可以动态地将方法传递给底层的具体值。这既有在运行时分配额外“盒子”以将实际值保存在大小一致且布局一致的容器内的成本,也有间接成本,因为盒子上的方法调用必须动态分派到底层类型Self使用具有- 或associatedtype要求的协议类型进行调用any协议类型前面的关键字是一个标记,有助于指示该类型被用作存在类型。现在它与使用协议的裸名称(即)完全相同,但已经有一些关于最终使用协议的裸名称来表示的讨论any P == Psome P因此,要解决您的具体示例:
\ninit(_ value: some BinaryInteger, radix: Int = 10, uppercase: Bool = false)\nRun Code Online (Sandbox Code Playgroud)\n与原来完全相同
\ninit<T>(_ value: T, radix: Int = 10, uppercase: Bool = false)\nwhere T : BinaryInteger\nRun Code Online (Sandbox Code Playgroud)\n尽管
\ninit(_ value: any BinaryInteger, radix: Int = 10, uppercase: Bool = false)\nRun Code Online (Sandbox Code Playgroud)\n不是。 而且,由于BinaryInteger有associatedtype要求,您也不能使用该any版本,因为存在类型不会提供对底层关联类型的访问。(如果你尝试,你就会得到经典error: protocol \'BinaryInteger\' can only be used as a generic constraint because it has Self or associated type requirements)
一般来说缺乏开销并且具有更大的灵活性;但是,它们需要知道参数的静态类型,但这并不总是可能的。
\n存在主义更容易接受输入,但功能明显受到限制,并且需要付出代价。
\n<T: P>在和some P、或P和之间any P\xe2\x80\x94 之间,选择目前是主观的,但是:
any关键字来表示存在协议的使用;与使用它相对应的是some,因此,如果您想开始使您的代码面向未来并保持一致,那么开始迁移到any和可能是一个好主意some