我有一个Swift包,里面有一个LinkedList类的实现。我想让我的LinkedList符合Sequence
协议。为此,makeIterator
返回LinkedListIterator
示例,它隐藏在不透明的IteratorProtocol
类型后面,如下所示:
extension LinkedList: Sequence {
public func makeIterator() -> some IteratorProtocol {
LinkedListIterator(head: head)
}
}
对于上面的opaque类型,当我想使用序列特性(如map
)时,我会出现编译错误:
func test_list_has_expected_elements() {
let list = LinkedList(2, 4, 2, 3)
XCTAssertEqual(list.map{ $0 }, [2, 4, 2, 3]) //Cannot convert value of type 'Int' to expected element type 'Array<(some IteratorProtocol).Element>.ArrayLiteralElement' (aka '(some IteratorProtocol).Element')
}
在将Sequence
一致性从opaque类型更改为LinkedListIterator<T>
之后,它编译时没有错误,但是它将LinkedListIterator
实现强制为public
,这是不希望的。
extension LinkedList: Sequence {
public func makeIterator() -> LinkedListIterator<T> {
LinkedListIterator(head: head)
}
}
如何将实现改为opaque
类型,并提供Sequence
API?
以下是我的LinkedList的完整实现:
public class LinkedList<T> {
var head: Node<T>?
init(_ elements : T...) {
if let first = elements.first {
var last = Node(data: first)
head = last
elements.dropFirst(1).forEach { element in
let next = Node(data: element)
last.next = next
last = next
}
}
}
public func append(data: T) {
let newNode = Node(data: data)
if let last {
last.next = newNode
} else {
head = newNode
}
}
public var count: UInt {
var runner = head
var count: UInt = 0
while let node = runner {
count += 1
runner = node.next
}
return count
}
private var last: Node<T>? {
if var runner = head {
while let next = runner.next {
runner = next
}
return runner
}
return nil
}
}
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
extension LinkedList: Sequence {
/*
public func makeIterator() -> LinkedListIterator<T> {
LinkedListIterator(head: head)
}
*/
public func makeIterator() -> some IteratorProtocol {
LinkedListIterator(head: head)
}
}
public struct LinkedListIterator<T>: IteratorProtocol {
private var currentNode: Node<T>?
init(head: Node<T>? = nil) {
self.currentNode = head
}
public mutating func next() -> T? {
if let node = currentNode {
currentNode = node.next
return node.data
} else {
return nil
}
}
}
Swift详细信息:swift-driver版本:1.62.15 Apple Swift版本5.7.1(swiftlang-5.7.1.135.3clang-1400.0.29.51)
2条答案
按热度按时间mwkjh3gx1#
你甚至会得到错误:
这是
opaque
类型的问题,你对它的associatedtype
类型一无所知。所以如果可以的话,最好返回确切的类型。当结果中有可怕的泛型时,只需要不透明的类型。k97glaaz2#
你只需要做一个小小的调整,它就会工作:
如果没有在T上专门化IteratorProtocol,编译器将认为它的Element是Any(即具有任何元素类型的不透明迭代器类型)。