自我协议

Car*_*ung 2 swift

我正在学习快速并正在使用Xcode。而且我总是深入研究定义。我看到了:

public protocol GeneratorType {
    typealias Element
    @warn_unused_result
    public mutating func next() -> Self.Element?
}
Run Code Online (Sandbox Code Playgroud)

符合此协议的结构:

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

我知道'Self'意味着返回符合类型。但是“ Self.Element”是什么意思?以及实现返回“ Elements._Element?”要求的函数,我看不到“ Elements._Element?” 等于“ Self.Element?”。有人可以向我解释吗?并告诉我更多有关此的信息。谢谢。

cou*_*elk 5

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

例如,在此斐波纳契数生成器中:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

...实现GeneratorType协议并指出其类型Element别名(Int在这种情况下),这就是生成器next()将要返回的类型(嗯,实际上是该类型的可选类型)。

不过,在实现参数化协议时,您常常不必显式地指定类型别名,因为Swift足够聪明,可以为您推断出它们。例如,对于上面示例中的斐波那契数生成器,以下操作也可以做到:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

... Swift从签名中next()知道它返回了Int?GeneratorType实现者也必须next()在他们的待办事项列表中,并且这些方法必须返回Element?类型。所以,斯威夫特只是把2和2在一起,并推断Element?必须是同样的事情Int?,因此Element == Int


对这个:

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

这里我们有四件事:

  • 我们声明一个通用类型IndexingGenerator,该通用类型采用称为的参数类型Elements
  • Elements类型具有必须实现Indexable协议的约束。
  • 我们实现发电机应该返回是通过访问类型值Indexable的接口Elements,这是众所周知的IndexingGenerator通过点语法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?
}
Run Code Online (Sandbox Code Playgroud)

最后,如果好奇为什么_Element而不是仅仅Element喜欢in GeneratorType,这就是他们在开源Swift仓库(在swift / stdlib / public / core / Collection.swift下)中写的内容:

_Element和下标的声明是一个技巧,用于打破Swift无法处理的循环一致性/推论。我们需要的不是a CollectionType.Generator.Element可以用作IndexingGenerator<T>的东西Element。在这里,我们安排CollectionType自身具有Element可以从其下标推断出的类型。理想情况下,我们希望将此限制Element为与相同CollectionType.Generator.Element,但今天我们无法表达它。