协议中的自我

时间:2016-02-19 12:08:24

标签: swift

我正在快速学习并使用Xcode。 我总是深入研究定义。我见过:

public protocol GeneratorType {
    typealias Element
    @warn_unused_result
    public mutating func next() -> Self.Element?
}

符合此协议的结构:

public struct IndexingGenerator<Elements : Indexable> : GeneratorType, SequenceType {
    public init(_ elements: Elements)
    public mutating func next() -> Elements._Element?
}

我知道&#39; Self&#39;表示返回符合类型。但是什么是Self.Element&#39;意思? 以及实现返回&#39; Elements._Element?&#39;的要求的功能,我看不到&#39; Elements._Element?&#39;等于&#39; Self.Element?&#39;。 谁有人向我解释这个? 并告诉我更多相关信息。谢谢。

1 个答案:

答案 0 :(得分:4)

Self.Element指的是实现GeneratorType协议的任何类型将声明为其Element类型的具体类型。

例如,在这个Fibonacci数的生成器中:

struct Fibonacci: GeneratorType {
    typealias Element = Int

    private var value: Int = 1
    private var previous: Int = 0

    mutating func next() -> Element? {
        let newValue = value + previous

        previous = value
        value = newValue

        return previous
    }
}

...您实施GeneratorType协议并指明其Element类型(在这种情况下为Int)的内容,这就是生成器next()将成为的类型返回(嗯,实际上是该类型的可选项)。

通常,在实现参数化协议时,您不必显式指定typealiases,因为Swift非常聪明,可以推断它们。例如。对于上面例子中的Fibonacci数字生成器,下面也会这样做:

struct Fibonacci: GeneratorType {
    private var value: Int = 1
    private var previous: Int = 0

    mutating func next() -> Int? {
        let newValue = value + previous

        previous = value
        value = newValue

        return previous
    }
}

...... Swift从next()的签名中知道它返回Int?,并且GeneratorType个实现者在其待办事项列表中也必须有next(),并且这些方法必须返回Element?类型。因此,Swift只将2和2放在一起,推断 Element?必须与Int?相同,因此Element == Int

关于这个:

public struct IndexingGenerator<Elements : Indexable> : GeneratorType, SequenceType {
    public init(_ elements: Elements)
    public mutating func next() -> Elements._Element?
}

我们有四件事情要做:

  • 我们声明泛型类型IndexingGenerator,它采用名为Elements的参数类型。
  • Elements类型具有必须实施Indexable协议的约束。
  • 我们实现的生成器应该返回可以通过Indexable Elements的{​​{1}}接口访问的类型的值,IndexingGenerator通过点语法将其称为{{1} }}。
  • Swift推断Elements._Element ElementIndexingGenerator相同。

因此,基本上上述宣言相当于:

Elements._Element

最后,如果对public struct IndexingGenerator<Elements : Indexable> : GeneratorType, SequenceType { public typealias Element = Elements._Element public init(_ elements: Elements) public mutating func next() -> Element? } 中的_Element而不仅仅是Element感到好奇,那么这就是他们在open-source Swift repository中所写的内容(在swift / stdlib / public / core下) /Collection.swift):

  

此处GeneratorType和下标的声明是用于打破Swift无法处理的循环一致性/演绎的技巧。我们需要_Element之外的其他内容,可用作CollectionType.Generator.Element的{​​{1}}。在这里,我们安排IndexingGenerator<T>本身具有Element类型,可从其下标中删除。理想情况下,我们希望将此CollectionType限制为与Element相同,但我们今天无法表达它。