我正在学习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
。
在您的示例中,您的实现仅";"解决";Iterator
associatedtype
:
public protocol MySequence {
func makeIterator() -> Self.Iterator
}
class MultiSet<T: Hashable> : Swift.Sequence {
func makeIterator() -> Array<T>.Iterator {
return data.makeIterator()
}
}
因为你"替换";在Iterator
和Array<T>.Iterator
的实现中,Swift了解应该如何解决Iterator
。但此时CCD_ 10仍未得到解决。
注意:Xcode在实现中确实要求
Element
和Iterator
类型的别名,但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
。