Reputation: 38025
I have a Node
class in Swift that implements Collection
so that each Node
acts recursively as a collection of child nodes of the same type.
The problem is when I subclass Node
, I still want the subclass to act as a collection of Node
s, but Swift won't even compile when I try to iterate over an instance of the subclass DerivedNode
, complaining that:
IndexingIterator<Node>
is not convertible toIndexingIterator<DerivedNode>
.
I'm confused why it would be trying to do this. I don't care about iterating over DerivedNode
s, they should continue to be iterated as Node
s.
Interestingly, the compiler/editor knows they should be of type Node
as the help popup shows the right type. But it still fails to compile for some reason.
Here's how I implemented the Collection
protocol:
extension Node: Collection {
public typealias Index = Int
public var startIndex: Int {
return 0
}
public var endIndex: Int {
return attributes.count
}
public func index(after i: Int) -> Int {
return i + 1
}
public subscript(i: Int) -> Node {
return attributes[i].value
}
}
Upvotes: 0
Views: 96
Reputation: 299495
If you do not declare an iterator, then Collection gives you one:
public func makeIterator() -> IndexingIterator<Self>
You don't want that one, though. You want IndexingIterator<Node>
. So you need to provide your own makeIterator()
method:
public func makeIterator() -> IndexingIterator<Node> {
return IndexingIterator(_elements: self)
}
This requires calling an undocumented initializer for IndexingIterator
. IMO that's a bug in the stdlib. Creating an IndexingIterator
by hand should be supported.
Upvotes: 1