2017-03-31 10 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(...), ...])

私はfor...inループ内でプリオーダーツリートラバーサルを可能にするためにシーケンス・プロトコルに準拠するようにNodeElementをしたいと思います。

これが行われる場合、これは

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 
     } 
    } 
} 

介して行うことができ、以下のERRORが発生します。

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

var content: [NodeElement] { get } 
      ^

これは私が完全にシーケンスプロトコルに準拠しています信じていた場合にも発生します。

NodeElementを構造体にしないで、すべてのノードに継承させることなく、この作業を行う方法はありますか?

+0

コヒーレントコード例を提供してください。あなたのプロトコルは、NodeElementを使用して定義されていますか、それはNodeElementと異なるか、または「タイプ」ですか?)また、コンテンツ変数もありません。それは子供や別の場所の何かと同じですか? –

+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 node in root.treeNodes 
{ 
    ... 
} 
関連する問題