Swift - 序列 - 为什么我不需要为 Element 和 Iterator 添加类型别名?

Swift - Sequence - Why I'm not required to add typealiases for Element and Iterator?

提问人:user14205680 提问时间:8/23/2021 更新时间:8/23/2021 访问量:153

问:

我正在学习 Swift,不明白为什么我可以声明

class MultiSet<T: Hashable> : Swift.Sequence {
    var data = [T]()
    
    func makeIterator() -> Array<T>.Iterator {
        return data.makeIterator()
    }
}

那会起作用的。但是,如果我复制声明并写Sequence

class MultiSet<T: Hashable> : MySequence {
    var data = [T]()
    
    func makeIterator() -> Array<T>.Iterator {
        return data.makeIterator()
    }
}

public protocol MySequence {
    associatedtype Element where Self.Element == Self.Iterator.Element
    associatedtype Iterator : IteratorProtocol
    func makeIterator() -> Self.Iterator
}

我遇到错误,需要显式写入协议存根:

    typealias Element = <#type#>
    typealias Iterator = <#type#>

它是如何自动推断的?

谢谢!

快速 序列

评论

0赞 8/23/2021
问得好。我怀疑这是对使用而不是 .TElement

答:

1赞 rraphael 8/23/2021 #1

这是因为您在声明中添加的约束只是一个约束,实际上并不能解析类型。associatedtype

为了能够解决 您需要在协议(或实现)中对该 .associatedtypeassociatedtype

在您的示例中,您的实现仅“解析”:Iteratorassociatedtype

public protocol MySequence {
    func makeIterator() -> Self.Iterator
}

class MultiSet<T: Hashable> : Swift.Sequence {
    func makeIterator() -> Array<T>.Iterator {
        return data.makeIterator()
    }
}

因为你在实现中“替换”了,所以 Swift 知道应该如何解决。但在这一点上仍然没有解决。IteratorArray<T>.IteratorIteratorElement

注意:Xcode 确实在实现中要求同时提供 和 类型别名,但实际上是唯一一个。 如果添加ElementIteratorElement

typealias Element = T

其中修复了错误。MultiSet

如果你想让 Swift 能够解析,你将需要同样类型的“引用”,无论是在你的实现中,还是在你的协议中直接使用扩展。ElementMultiSet

例如:

public protocol MySequence {
    associatedtype Element where Self.Element == Self.Iterator.Element
    associatedtype Iterator : IteratorProtocol
    func makeIterator() -> Iterator

    func foobar() -> Element? // added a reference to Element
}

extension MySequence {
    func foobar() -> Iterator.Element? {
        nil
    }
}

struct MultiSet<T>: MySequence {
    var data = [T]()

    func makeIterator() -> Array<T>.Iterator {
        return data.makeIterator()
    }
}

这将允许 Swift 解析为 .ElementIterator.Element

注意:您可以在没有扩展中默认实现的情况下进行 inside 定义。我用了这个例子,因为它是在里面完成的。foobarMultiSetSequence

如果你看一下实现(源代码),你会注意到函数(引用),有一个默认的实现(解析为Sequence_customContainsEquatableElementElementElementIterator.Element)

public protocol Sequence {
  func _customContainsEquatableElement(
    _ element: Element
  ) -> Bool?
}

// [...]

extension Sequence {
  public func _customContainsEquatableElement(
    _ element: Iterator.Element
  ) -> Bool? {
    return nil
  }
}

这就是为什么在实现时不必显式解析 ,它被隐式解析为 。SequenceElementIterator.Element

评论

0赞 user14205680 8/24/2021
谢谢!这确实解释了