2017-03-31 58 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 
{ 
    ... 
}