代码之家  ›  专栏  ›  技术社区  ›  Oskar

阵列中的协议和关联类型

  •  2
  • Oskar  · 技术社区  · 6 年前

    我有协议 Node :

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

    由类实现:

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

    但这就带来了一个问题,即在 TreeNode 现在给我一个 结点 我想去做 树冠 具体操作。所以我想把协议改为:

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

    我将类定义为:

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

    伟大的!但有一个陷阱。如果我想为 结点 它处理数组:

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

    编译器失败,错误为: Cannot convert return expression of type 'ReversedCollection<[T.T]>' to return type '[T]'

    根据我对这个问题的了解,我需要实现一个类型擦除机制来支持这个体系结构。但是如何在我的例子中做到这一点呢?

    1 回复  |  直到 6 年前
        1
  •  3
  •   Martin R    6 年前

    您可能希望节点的父节点和子节点属于 同类型 作为节点本身,而不仅仅是 一些 类型符合 Node . 那将是 Self 在协议定义中:

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

    现在,您可以定义具体的类(请参见 A Swift protocol requirement that can only be satisfied by using a final class 为什么要上课 final ):

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

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

    编译没有问题。