2016-03-25 4 views
2

私はSwiftでランダム化ツリーデータ構造を実装しています。ツリーの幅と深さを制限するために、ポリシー(戦略)パターンを使用することに決めました。Swift:ネスト/連鎖ジェネリック型制約を使用できません(ポリシーパターン)

私のポリシーは次のようになります。

protocol BaseTreeNodePolicy { 
    static var maximumDepth: Int { get } 
    static var maximumWidth: Int { get } 
} 

と、私はこのようになります基本クラスを持っている:

class BaseTreeNode<PolicyType: BaseTreeNodePolicy> { /* ... */ } 

それのいくつかのサブクラス:

class ValueNode<ValueType, PolicyType: BaseTreeNodePolicy>: BaseTreeNode<PolicyType> { /* ... */ } 
class ActionNode<PolicyType: BaseTreeNodePolicy>: BaseTreeNode<PolicyType> { /* ... */ } 

はすべてが働いていますよくこのクラスを追加するまで:

// 'ChildType' is not a subtype of 'ActionNode<PolicyType>' 
sequence.reserveCapacity(42) 

と、この行::私は、私ははっきりと言っタイプの要件を国家として間違って何見当がつかない

// Type 'PolicyType' does not conform to protocol 'BaseTreeNodePolicy' 
let descendant = ChildType(generator: generator, maxDepth: maxDepth - 1) 
final class SequenceNode<ChildType: ActionNode<PolicyType>, PolicyType: BaseTreeNodePolicy>: ActionNode<PolicyType> { 
    public var sequence: [ChildType] = [] 
    // ... 
    public override func addRandomDescendants(generator: EntropyGenerator, maxDepth: Int) { 
     // ... 
     sequence.reserveCapacity(42) 
     // ... 
     let descendant = ChildType(generator: generator, maxDepth: maxDepth - 1) 
     // ... 
    } 
} 

SequenceNodeをコンパイルし、私はこの行のコンパイルエラーを取得しますChildType: ActionNode<PolicyType>PolicyType: BaseTreeNodePolicyが宣言のヘッダー部分にあります。

何が間違っている可能性がありますか?

ありがとうございます! Petr。

答えて

3

EDIT:あなたの目的に到達するために再実行します。

ActionNode<PolicyType>

は、パラメータリストに属していません。あなただけ PolicyTypeにパラメータ化している:

final class SequenceNode<PolicyType: BaseTreeNodePolicy> { 
    typealias ChildType = ActionNode<PolicyType> 
    var sequence = [ChildType]() 
    func addRandomDescendants(generator: EntropyGenerator, maxDepth: Int) { 
     sequence.reserveCapacity(42) 
    } 
} 

EDIT 2:今、あなたは、より汎用的になりたいです。 [OK]をクリックします。ただし、チェーンタイプの依存関係にはなりません。WITHINジェネリック型制約リスト。タイプ制約は直接解決可能でなければなりません。これは、エラーを明確にする必要があります。

class _ERROR_SequenceNode<PolicyType, ChildType where PolicyType: BaseTreeNodePolicy, ChildType: ActionNode<PolicyType>> { } 

スーパークラス制約「ActionNode」は、コンクリートではありませんので、しかし、また、あなたPolicyTypeの代わりにBaseTreeNodePolicyを使用することはできません型パラメータ

に依存することはできません:

プロトコル 'BaseTreeNo'に準拠した具体的なタイプとして 'BaseTreeNodePolicy'を使用するChildTypeがすでにジェネリック型を直接インスタンス化しなければならないことを、一般的なタイプですでに拘束されているので、dePolicyは」したがって、それだけで、それ自体が、外部の、知られているによって制約コンクリートすることができ、そう

がサポートされていません。 BaseTreeNodePolicyの実装。

BIG PICTURE

しかし、私は単に仕事を得るためのアイデアが不足している間、あなたがジェネリックに絡まるていると思います。汎用型を使用してパラメータ化する場合、型システムのその支店を完全に制御しているときには値はありません。*関数から汎用化型*を返す必要はありません。言い換えれば

私のクラスのユーザーが合法getKey()関数からの戻り値はそのコードでは、ないタイプHashableの実際の型であることを期待するので、私はFooKeyTypeFooKeyType: Hashableに包括的にパラメータ化されたハッシュテーブルを構築する必要があります。ここではpolicyオブジェクトを返すことはありません。そうしたとしても、具体的な具体的なポリシータイプではなく、返されるタイプがBaseTreeNodePolicyに固定されていることに気を付けるべきではありません。

格納されたプロパティを必要なプロトコルとして抽象的に型制約することによって、制約できます。

は考えてみましょう:それは私が思ったよりも簡単です

protocol BaseTreeNodePolicy { 
    var maximumDepth: Int { get } 
    var maximumWidth: Int { get } 
} 

class BaseTreeNode { 
    var policy: BaseTreeNodePolicy 

    required init(policy: BaseTreeNodePolicy) { 
     self.policy = policy 
    } 

    // Use 'policy' anywhere now. You've defined a protocol, don't generically parameterize 
} 

class ValueNode: BaseTreeNode { 
    required init(policy: BaseTreeNodePolicy) { 
     super.init(policy: policy) 
    } 
} 

class ActionNode: BaseTreeNode { 
    required init(policy: BaseTreeNodePolicy) { 
     super.init(policy: policy) 
    } 
} 

class SequenceNode<ChildType: ActionNode>: BaseTreeNode { 
    var sequence: [ChildType] = [] 

    required init(policy: BaseTreeNodePolicy) { 
     super.init(policy: policy) 
    } 

    func addRandomDescendants() { 
     let c = ChildType(policy: policy) 
     sequence.reserveCapacity(42) 
    } 
} 

class FooNode: ActionNode {} 

class MyPolicy: BaseTreeNodePolicy { 
    var maximumDepth = 3 
    var maximumWidth = 5 
} 

let s = SequenceNode<FooNode>(policy: MyPolicy()) 
+0

、これを試してみてください。 – BaseZen

+0

良い解決策ですが、 'ChildType'を' ActionNode 'のサブクラスにしたいのですが? –

+0

OK、やり直しますが、思考にシフトが必要です。 – BaseZen

関連する問題