Reputation: 230
I've been trying to extend a swift array that hold specific type.
protocol Node {
var nodeId: Int { get }
var parentId: Int? { get }
var children: [Node] { get set }
var level: Int { get set }
}
extension Array where Element : Node {
/**
unflatten an array of Nodes.
*/
func unflattenNodes()-> [Node] {
func unflatten(inout parent: Node?)-> [Node] {
var topNodes = [Node]()
let children = self.filter{ (child: Node) in return child.parentId == parent?.nodeId ?? 0 }
if !children.isEmpty {
if var parent = parent {
for var child in children {
child.level = parent.level + 1
}
parent.children = children
}
else {
topNodes = children
}
for child in children {
var optChild = Optional(child)
unflatten(&optChild)
}
}
return topNodes;
}
var optChild: Node? = nil
return unflatten(&optChild)
}
}
This code above won't be compiled because 'Node' is not subtype of 'Element', even though I'm extending Array of element "Node". How can I archive what I'm trying to do here in swift? I'm trying to add an instance method to [Node] to unflatten self.
Upvotes: 0
Views: 633
Reputation: 230
Updating extension Array where Element : Node
to extension CollectionType where Generator.Element == Node
resolved the error.
Upvotes: 1
Reputation: 86651
Right, I've plugged the code into Playground and I found three issues. The first is the one mentioned by Kametrixom which is that you need to use Element
as the type everywhere in unflattenNodes
. When you have fixed that and got rid of all the parent:
in the calls to unflatten
, you'll be left with one error
parent.children = children
error: cannot assign a value of type '[Element]' to a value of type '[Node]'
parent.children = children
^
This is caused by the fact that the children
property in the protocol is defined as [Node]
and Swift can't match it to an array of Element
So you need to change the protocol
protocol Node {
var nodeId: Int { get }
var parentId: Int? { get }
var children: [Self] { get set }
// ^^^^^^ Here
var level: Int { get set }
}
The children
property is no longer an array of Node
but an array of whatever type is conforming to the protocol, in your case, Element
Upvotes: 1
Reputation: 14973
The problem is that the protocol Node
doesn't conform to itself: Node
is not of type Node
(as contradicting as it sounds), because a protocol isn't a concrete type, it's just a requirement for the conforming type.
That said, you need to replace every instance of Node
in your code with Element
, then it should work (can't test it right now). This is because again, you're actually not handling some value of type Node
, but rather a value of a type that conforms to Node
(Element
in your case)
Also you made a few other mistakes in your code, I'll leave that to someone else to correct as I'm out of time.
Upvotes: 1