什么是 "Element" 类型?
What is "Element" type?
正在阅读 Swift 编程语言 一书我看过很多对类型 Element
的引用,它用于定义集合项的类型。但是,我找不到任何关于它的文档,是 class、协议吗?它有什么样的functionality/methods/properties?
struct Stack<Element>: Container {
// original Stack<Element> implementation
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
...
Element
通常用作集合的通用类型名称,如
public struct Array<Element> { ... }
所以它是你构建数组的依据,而不是语言预定义的东西。
这是Apple文档中的定义
Element defines a placeholder name for a type to be provided later.
This future type can be referred to as Element anywhere within the
structure’s definition.
如果我们尝试追溯我们在处理集合时如何获得 Element
的想法,我们会注意到它与 Iterator 协议。让我们更清楚一点:
Swift Collection types (Array, Dictionary and Set) are all conforms to Collection protocol. Therefore, when it comes to the Collection protocol, we can see that the root of it is the Sequence protocol:
A type that provides sequential, iterated access to its elements.
Sequence 有一个 Element 和 Iterator 关联类型,声明为:
associatedtype Element
associatedtype Iterator : IteratorProtocol where Iterator.Element == Element
您可以在序列 source code 上查看它。
如图,Iterator
也有一个Element associated type,跟序列Element比较,那是什么意思呢?
IteratorProtocol
是执行实际工作的那个:
The IteratorProtocol protocol is tightly linked with the Sequence
protocol. Sequences provide access to their elements by creating an
iterator, which keeps track of its iteration process and returns one
element at a time as it advances through the sequence.
因此,Element 将是返回到序列的元素的类型。
编码:
为了简单易懂,你可以实现这样一个代码来模拟案例:
protocol MyProtocol {
associatedtype MyElement
}
extension MyProtocol where MyElement == String {
func sayHello() {
print("Hello")
}
}
struct MyStruct: MyProtocol {
typealias MyElement = String
}
MyStruct().sayHello()
请注意 - 如上所示 - 实现对 MyProtocol
的扩展使得 MyElement
关联类型对 where 子句有意义。
因此,sayHello()
方法仅适用于将字符串分配给 MyElement
的 MyProtocol
类型(在我们的例子中为 MyStruct
),这意味着如果 MyStruct
已实施为:
struct MyStruct: MyProtocol {
typealias MyElement = Int
}
您将不能能够:
MyStruct().sayHello()
您应该会看到一个编译时错误:
'MyStruct.MyElement' (aka 'Int') is not convertible to 'String'
Swift 集合类型的逻辑相同:
extension Array where Element == String {
func sayHello() {
print("Hello")
}
}
Element
是结构的专用(和定义)占位符。 与某些 answers/comments 所建议的不同,Element
不能总是替代 T
,因为没有适当上下文的 T
是未定义的。例如,以下不会编译:
infix operator ++
extension Array {
static func ++ (left: Array<T>, right: T) -> Array {
...
}
}
编译器不知道 T
是什么,它只是一个任意字母——它可以是任何字母,甚至是符号(T
刚刚变成 Swift 约定) .然而,这个将编译:
infix operator ++
extension Array {
static func ++ (left: Array<Element>, right: Element) -> Array {
...
}
}
它编译是因为编译器知道 Element
是什么,一个定义的占位符,而不是一个任意组成的类型。
正在阅读 Swift 编程语言 一书我看过很多对类型 Element
的引用,它用于定义集合项的类型。但是,我找不到任何关于它的文档,是 class、协议吗?它有什么样的functionality/methods/properties?
struct Stack<Element>: Container {
// original Stack<Element> implementation
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
...
Element
通常用作集合的通用类型名称,如
public struct Array<Element> { ... }
所以它是你构建数组的依据,而不是语言预定义的东西。
这是Apple文档中的定义
Element defines a placeholder name for a type to be provided later. This future type can be referred to as Element anywhere within the structure’s definition.
如果我们尝试追溯我们在处理集合时如何获得 Element
的想法,我们会注意到它与 Iterator 协议。让我们更清楚一点:
Swift Collection types (Array, Dictionary and Set) are all conforms to Collection protocol. Therefore, when it comes to the Collection protocol, we can see that the root of it is the Sequence protocol:
A type that provides sequential, iterated access to its elements.
Sequence 有一个 Element 和 Iterator 关联类型,声明为:
associatedtype Element
associatedtype Iterator : IteratorProtocol where Iterator.Element == Element
您可以在序列 source code 上查看它。
如图,Iterator
也有一个Element associated type,跟序列Element比较,那是什么意思呢?
IteratorProtocol
是执行实际工作的那个:
The IteratorProtocol protocol is tightly linked with the Sequence protocol. Sequences provide access to their elements by creating an iterator, which keeps track of its iteration process and returns one element at a time as it advances through the sequence.
因此,Element 将是返回到序列的元素的类型。
编码:
为了简单易懂,你可以实现这样一个代码来模拟案例:
protocol MyProtocol {
associatedtype MyElement
}
extension MyProtocol where MyElement == String {
func sayHello() {
print("Hello")
}
}
struct MyStruct: MyProtocol {
typealias MyElement = String
}
MyStruct().sayHello()
请注意 - 如上所示 - 实现对 MyProtocol
的扩展使得 MyElement
关联类型对 where 子句有意义。
因此,sayHello()
方法仅适用于将字符串分配给 MyElement
的 MyProtocol
类型(在我们的例子中为 MyStruct
),这意味着如果 MyStruct
已实施为:
struct MyStruct: MyProtocol {
typealias MyElement = Int
}
您将不能能够:
MyStruct().sayHello()
您应该会看到一个编译时错误:
'MyStruct.MyElement' (aka 'Int') is not convertible to 'String'
Swift 集合类型的逻辑相同:
extension Array where Element == String {
func sayHello() {
print("Hello")
}
}
Element
是结构的专用(和定义)占位符。 与某些 answers/comments 所建议的不同,Element
不能总是替代 T
,因为没有适当上下文的 T
是未定义的。例如,以下不会编译:
infix operator ++
extension Array {
static func ++ (left: Array<T>, right: T) -> Array {
...
}
}
编译器不知道 T
是什么,它只是一个任意字母——它可以是任何字母,甚至是符号(T
刚刚变成 Swift 约定) .然而,这个将编译:
infix operator ++
extension Array {
static func ++ (left: Array<Element>, right: Element) -> Array {
...
}
}
它编译是因为编译器知道 Element
是什么,一个定义的占位符,而不是一个任意组成的类型。