前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Swift5.7: 泛型类型支持带尖括号的扩展绑定

Swift5.7: 泛型类型支持带尖括号的扩展绑定

原创
作者头像
DerekYuYi
发布2022-12-01 12:51:18
1.4K0
发布2022-12-01 12:51:18
举报
文章被收录于专栏:Swift-开源分析

介绍

SE-0361,在 Swift5.7 已经实现。

目前指定泛型的类型参数基本都是通过<>来表示,例如Array<String>。但是Extension是个例外,因为如果你想为了某个泛型添加Extension, 并且指定参数类型,使用<>指定泛型约束的类型如String,此时编译器会报错,例如:

代码语言:Swift
复制
extension Array<String> { ... } ❌ // error: Constrained extension must be declared on the unspecialized generic type 'Array' with constraints specified by a 'where' clause

此时,编译器会告诉你使用where子句来为extension添加受约束的类型,例如:

代码语言:Swift
复制
extension Array where Element == String {  ...  } ✅

本篇提议的目的就是为了移除extension上对泛型参数声明的限制,允许通过<>来声明约束的泛型参数。

提议动机

在 Swift 语言中,基本到处可见使用<>在泛型类型名称后面声明绑定的泛型类型。例如,我们可以声明一个别名StringArray, 这个别名代表Array<String>类型,然后我们再对别名进行扩展:

代码语言:Swift
复制
typealias StringArray = Array<String>
extension StringArray { ... }

结合0346, 我们还可以为协议声明一个主要关联类型,并且使用<>绑定到扩展声明上,例如:

代码语言:Swift
复制
protocol Collection<Element> {
    associatedtype Element
}
extension Collection<String> { ... }

但是编译器不允许直接在扩展上使用这个语法绑定泛型类型,这种限制确实很让开发者困惑。

代码语言:Swift
复制
extension Array<String> { ... } // error: Constrained extension must be declared on the unspecialized generic type 'Array' with constraints specified by a 'where' clause

所以本篇提议是为了去掉这个限制,任何地方为泛型类型约束参数类型都可以使用<typename>方式。

提议解决方案

本篇文章提议使用<>绑定参数类型来扩展绑定泛型类型,或者使用语法糖[String]Int?

String为例子,如果要为元素为String类型的数组进行扩展,我们有以下三种方式可以声明:

代码语言:Swift
复制
/// 1. 最原始方式
extension Array where Element == String {  ... }
/// 2. 尖括号方式
extension Array<String> { ... }
/// 3. 语法糖方式
extension [String] { ... }

设计细节

扩展的泛型类型名称可以由尖括号中,隔开的类型参数列表组成。 类型参数列表将泛型类型的类型参数绑定到每个指定的类型参数。这种写法最终跟where子句表达等价。例如:

代码语言:Swift
复制
struct Pair<T, U> {}

extension Pair<Int, String> {}

extension 与下面where语句等价:

代码语言:Swift
复制
extension Pair where T == Int, U == String {}

设计需要遵循几个规则:

  • 对泛型类型扩展,它的类型参数列表在扩展时,必须指定所有的类型参数。如果在扩展中只约束类型参数中的一个,此时还需要使用where子句。例如:
代码语言:Swift
复制
struct Pair <T, U> {}

extension Pair<Int> {} // ❌ error: Generic type 'Pair' specialized with too few type parameters (got 1, but expected 2)

extension Pair where T == Int {} // ✅
  • 指定的参数必须是明确的类型,不能在扩展时使用默认占位符_来代替参数:
代码语言:Swift
复制
extension Pair<Int, _> {} // ❌ error: Cannot extend a type that contains placeholders

理由:当使用_来代替参数时,它会让编译器根据上下文推断默认参数的类型,这个类型也就变得不受约束,而且Pair<Int, _>在不同的上下文,也意味不同的表达,完全不受控制。

  • 类型参数的查找是在扩展上下文之外进行的,所以泛型类型的参数是不能出现类型参数列表中。因为泛型类型的参数在上下文中,无法代表一个准确的类型。比如Element
代码语言:Swift
复制
extension Array<Element> {} // error: Cannot find type 'Element' in scope
  • 如果用于扩展的泛型支持语法糖,那么扩展时同样支持语法糖,比如[String]
代码语言:Swift
复制
extension [String] { ... } // Extends Array<String>

extension String? { ... } // Extends Optional<String>

总结

  1. Swift5.7 泛型类型支持带尖括号的扩展绑定
  2. 至此,包括 extension, Swift 均支持带<>扩展语法

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 提议动机
  • 提议解决方案
  • 设计细节
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档