Swift - 序列 - 为什么我不需要为元素和迭代器添加类型别名?
Swift - Sequence - Why I'm not required to add typealiases for Element and Iterator?
我正在学习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()
}
}
因为你在实现中用Array<T>.Iterator
“替换”了Iterator
,Swift明白了Iterator
应该如何解决。但是那个时候Element
还是没有解决。
Note: Xcode does ask for both Element
and Iterator
type aliases in the implementation, but Element
is the only one actually missing.
If you add
typealias Element = T
In MultiSet
it fixes the error.
如果您希望 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
。
Note: You can define foobar
inside MultiSet
without a default implementation in an extension. I used this example because it is how it's done inside Sequence
.
如果您看一下 Sequence
实现 (Source code),您会注意到 _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
。
我正在学习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()
}
}
因为你在实现中用Array<T>.Iterator
“替换”了Iterator
,Swift明白了Iterator
应该如何解决。但是那个时候Element
还是没有解决。
Note: Xcode does ask for both
Element
andIterator
type aliases in the implementation, butElement
is the only one actually missing. If you addtypealias Element = T
In
MultiSet
it fixes the error.
如果您希望 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
。
Note: You can define
foobar
insideMultiSet
without a default implementation in an extension. I used this example because it is how it's done insideSequence
.
如果您看一下 Sequence
实现 (Source code),您会注意到 _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
。