2017-03-31 64 views
0

试图创建一个用于在树内创建不同节点的协议。一个简化的版本是:协议符合序列协议,同时消除通用约束问题

protocol NodeElement { 
    var children: [NodeElement] { get } 
} 

这个协议可以被用来创建结构 s表示可以用来创建节点成树。

struct TextNode: NodeElement { 
    var text: String 
    var children: [NodeElement] 
} 

struct NumberNode: NodeElement { 
    var number: Int 
    var children: [NodeElement] 
} 

以及与这些结构,可以创建一个树含有不同类型。

let root = TextNode(text: "Hello", children: [NumberNode(...), ...])

我想NodeElement以符合序列协议以允许for...in环路内预购树的遍历。

error: protocol 'NodeElement' can only be used as a generic constraint 
because it has Self or associated type requirements 

var content: [NodeElement] { get } 
      ^

的时候,我相信我完全符合序列协议会出现这种情况:

这可以通过

protocol NodeElement: Sequence { ... } 

extension NodeElement { 
    func makeIterator() -> AnyIterator<NodeElement> { 
     var stack: [NodeElement] = [self] 

     return AnyIterator { 
      if let next = stack.first { 
       stack.remove(at: 0) 
       stack.insert(contentsOf: next.content, at: 0) 
       return next 
      } 
      return nil 
     } 
    } 
} 

如果做到这一点,下面错误发生来完成。

没有使NodeElement 结构和所有节点从它继承,有什么办法可以使这个工作?

+0

请提供一致的代码示例。您的协议是使用NodeElements定义的,与NodeElement不同还是“s”是错字)?它也没有内容变量。这与孩子或其他地方的其他人一样吗? –

+0

它们是相同的,它在代码示例中已得到修复。 –

回答

0

NodeElement具有对自身的引用,因此它不能用于定义具体类型。因此,您无法将其制作为序列。

然而,您可以通过简单地将计算变量添加到协议而不是将其作为序列本身来实现类似的功能。

例如:

extension NodeElement 
{ 
    var treeNodes : AnyIterator<NodeElement> 
    { 
     var stack: [NodeElement] = [self] 

     return AnyIterator { 
      if let next = stack.first { 
       stack.remove(at: 0) 
       stack.insert(contentsOf: next.children, at: 0) 
       return next 
      } 
      return nil 
     } 
    } 
} 

然后,您将能够使用您的协议在for ... in循环使用变量:

for node in root.treeNodes 
{ 
    ... 
}