什么是"元素"类型?

时间:2018-04-15 08:30:10

标签: swift collections element

阅读 Swift编程语言一书我已经看到了Element类型的引用数,用于定义集合项的类型。但是,我找不到任何关于它的文档,是类,协议吗?它有什么样的功能/方法/属性?

struct Stack<Element>: Container {
    // original Stack<Element> implementation
    var items = [Element]()
    mutating func push(_ item: Element) {
        items.append(item)
    }
    ...

4 个答案:

答案 0 :(得分:3)

以下是Apple文档

中的定义
  

元素为稍后提供的类型定义占位符名称。   这种未来类型可以在其中的任何地方称为元素   结构的定义。

答案 1 :(得分:1)

Element通常用作集合的通用类型名称,如

public struct Array<Element> { ... }

所以这是你构建你的数组,而不是语言预定义的东西。

答案 2 :(得分:1)

如果我们尝试跟踪在使用集合时我们如何获得Element的想法,我们会注意到它与 Iterator 协议有关。让我们说清楚:

Swift Collection typesArrayDictionarySet)都符合Collection protocol。因此,当涉及到Collection协议时,我们可以看到它的根是Sequence protocol

  

提供对其元素的顺序,迭代访问的类型。

序列有一个元素迭代器相关类型,声明为:

associatedtype Element

associatedtype Iterator : IteratorProtocol where Iterator.Element == Element

您可以在序列{​​{3}}上查看它。

如图所示,Iterator也有source code,与序列元素进行比较,这意味着什么?

Element associated type是完成实际工作的人:

  

IteratorProtocol协议与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()方法仅适用于MyProtocol类型(在我们的例子中为MyStruct),它将字符串分配给MyElement,表示如果MyStruct具有已实施为:

struct MyStruct: MyProtocol {
    typealias MyElement = Int
}

你将 能够:

MyStruct().sayHello()

您应该看到编译时错误:

  

&#39; MyStruct.MyElement&#39; (又名&#39; Int&#39;)不能转换为&#39; String&#39;

Swift集合类型的逻辑相同:

extension Array where Element == String {
    func sayHello() {
        print("Hello")
    }
}

答案 3 :(得分:1)

Element是用于结构的专用(且已定义)占位符。 与某些答案/建议不同,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是什么,它是定义的占位符,而不是任意组成的类型。