SE-0361,在 Swift5.7 已经实现。
目前指定泛型的类型参数基本都是通过<>
来表示,例如Array<String>
。但是Extension
是个例外,因为如果你想为了某个泛型添加Extension
, 并且指定参数类型,使用<>
指定泛型约束的类型如String
,此时编译器会报错,例如:
extension Array<String> { ... } ❌ // error: Constrained extension must be declared on the unspecialized generic type 'Array' with constraints specified by a 'where' clause
此时,编译器会告诉你使用where
子句来为extension
添加受约束的类型,例如:
extension Array where Element == String { ... } ✅
本篇提议的目的就是为了移除extension
上对泛型参数声明的限制,允许通过<>
来声明约束的泛型参数。
在 Swift 语言中,基本到处可见使用<>
在泛型类型名称后面声明绑定的泛型类型。例如,我们可以声明一个别名StringArray
, 这个别名代表Array<String>
类型,然后我们再对别名进行扩展:
typealias StringArray = Array<String>
extension StringArray { ... }
结合0346, 我们还可以为协议声明一个主要关联类型,并且使用<>
绑定到扩展声明上,例如:
protocol Collection<Element> {
associatedtype Element
}
extension Collection<String> { ... }
但是编译器不允许直接在扩展上使用这个语法绑定泛型类型,这种限制确实很让开发者困惑。
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
类型的数组进行扩展,我们有以下三种方式可以声明:
/// 1. 最原始方式
extension Array where Element == String { ... }
/// 2. 尖括号方式
extension Array<String> { ... }
/// 3. 语法糖方式
extension [String] { ... }
扩展的泛型类型名称可以由尖括号中,
隔开的类型参数列表组成。 类型参数列表将泛型类型的类型参数绑定到每个指定的类型参数。这种写法最终跟where
子句表达等价。例如:
struct Pair<T, U> {}
extension Pair<Int, String> {}
extension 与下面where
语句等价:
extension Pair where T == Int, U == String {}
设计需要遵循几个规则:
where
子句。例如: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 {} // ✅
_
来代替参数:extension Pair<Int, _> {} // ❌ error: Cannot extend a type that contains placeholders
理由:当使用
_
来代替参数时,它会让编译器根据上下文推断默认参数的类型,这个类型也就变得不受约束,而且Pair<Int, _>
在不同的上下文,也意味不同的表达,完全不受控制。
Element
。extension Array<Element> {} // error: Cannot find type 'Element' in scope
[String]
:extension [String] { ... } // Extends Array<String>
extension String? { ... } // Extends Optional<String>
<>
扩展语法原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。