2

I have a protocol Node:

protocol Node {
   var parent: Node?
   var children: [Node]
}

which is implemented by classes:

class TreeNode: Node {
   var parent: Node?
   var children: [Node]
}

But this poses a problem as accessing the parent in TreeNode now gives me a Node, and I want to do TreeNode specific operations on them. So I want to change the protocol to:

protocol Node {
   associatedtype T: Node

   var parent: T?
   var children: [T]
}

Which let's me define the class as:

class TreeNode: Node {
   var parent: TreeNode?
   var children: [TreeNode]
}

Great! But there's a catch. If I want to write a helper method for Node that deals with arrays:

func getReversedChildren<T: Node>(node: T) -> [T] {
   return node.children.reversed()
}

The compiler fails with the error: Cannot convert return expression of type 'ReversedCollection<[T.T]>' to return type '[T]'

From what I can gather about this issue, I need to achieve a type-erasure mechanism to support this architecture. But how can this be done on my example?

2
  • 1
    How is ArcNode defined ? Commented Jan 19, 2019 at 13:31
  • @claude31 Typo, should be Node. Updated question Commented Jan 19, 2019 at 15:56

1 Answer 1

3

You probably want the parent and children of a node to be of the same type as the node itself, not just some type conforming to Node. That would be Self in the protocol definition:

protocol Node {
    var parent: Self? { get set }
    var children: [Self] { get set }
}

Now you can define the concrete class (see A Swift protocol requirement that can only be satisfied by using a final class for why the class needs to be final):

final class TreeNode: Node {
    var parent: TreeNode? = nil
    var children: [TreeNode] = []
}

and

func getReversedChildren<T: Node>(node: T) -> [T] {
    return node.children.reversed()
}

compiles without problems.

Sign up to request clarification or add additional context in comments.

1 Comment

This is it! Thank you :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.