首页 > 解决方案 > 数组中的协议和关联类型

问题描述

我有一个协议Node

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

这是由类实现的:

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

但这带来了一个问题,因为TreeNode现在访问父级给了我一个Node,我想TreeNode对它们进行特定的操作。所以我想将协议更改为:

protocol Node {
   associatedtype T: Node

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

让我将类定义为:

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

伟大的!但有一个问题。如果我想为Node处理数组编写一个辅助方法:

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

编译器失败并出现以下错误: Cannot convert return expression of type 'ReversedCollection<[T.T]>' to return type '[T]'

从我能收集到的关于这个问题的信息来看,我需要实现一种类型擦除机制来支持这种架构。但是如何在我的例子中做到这一点?

标签: swiftgenericsprotocolsswift-protocols

解决方案


您可能希望节点的父节点和子节点与节点本身的类型相同,而不仅仅是符合. 那将在协议定义中:NodeSelf

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

现在您可以定义具体的类(请参阅A Swift 协议要求,该要求只能通过使用最终类来满足,以了解为什么需要该类final):

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

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

编译没有问题。


推荐阅读