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



我正在学习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#>

它是如何自动推断的?

谢谢!

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

为了能够解析associatedtype,您需要在协议(或实现)中引用该associatedtype

在您的示例中,您的实现仅";"解决";Iteratorassociatedtype:

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

因为你"替换";在IteratorArray<T>.Iterator的实现中,Swift了解应该如何解决Iterator。但此时CCD_ 10仍未得到解决。

注意:Xcode在实现中确实要求ElementIterator类型的别名,但Element是唯一实际缺少的别名。如果添加

typealias Element = T

MultiSet中,它修复了错误。

如果您希望Swift能够解析Element,您将需要相同类型的";参考";,无论是在MultiSet的实现中,还是直接在带有扩展的协议中。

例如:

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将Element解析为Iterator.Element

注意:您可以在MultiSet中定义foobar,而无需在扩展中使用默认实现。我使用这个例子是因为它是如何在Sequence中完成的。

如果您查看Sequence实现(源代码),您会注意到_customContainsEquatableElement函数(引用Element),它有一个默认实现(将Element解析为Iterator.Element)

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

这就是为什么在实现Sequence时不必显式解析Element,而是隐式解析为Iterator.Element

相关内容

  • 没有找到相关文章

最新更新