2016-05-25 21 views
4

は、次のコードを考えてみましょう。残念なことに、イニシャライザ(またはプロパティ定義自体)にデフォルト値を指定すると、コンパイラは "InnerParser型のデフォルト引数値を 'T' '型に変換できません。一般的な制約タイプのデフォルト値

デフォルト値の割り当てを削除して、InnerParserを明示的に指定してOuterParserをインスタンス化するだけであれば、問題ありません。

let outerParser = OuterParser(innerParser: InnerParser()) 
私の質問は、実際に制約を満たすデフォルト値を提供するアプローチが機能しない理由です。

答えて

1

タイプTは、クラスによって定義されていません。クラスを使用するコードで定義されています。したがって、クラス内で何かを行う前に(インスタンスまたは静的レベルで)定義されます。したがって、InnerParserTに割り当てることはできません。Tはすでに指定されており、その時点までに指定されたタイプはInnerParserではない可能性があります。

struct AnotherParser: JSONParserType { 
    typealias Element = Item 
} 

をとのあなたの現在のコードがコンパイルされることを想定してみましょう:

たとえば、あなたが別のパーサー構造体を持っていることを考えてみましょう。今、あなたはこれを行う際に何が起こるかを考えてみます。

let parser = OuterParser<AnotherParser>() 

あなたはAnotherParserするジェネリック型を定義した - しかし、初期化子は(今のタイプAnotherParserの)あなたの財産にInnerParserを割り当てようとします。これらのタイプは一致しないため、動作しない可能性があります。

同じロジックに続いて、この実装は動作しません。

struct OuterParser<T: JSONParserType where T.Element == Item>: JSONParserType { 
    typealias Element = Item 
    let innerParser: T 

    init() { 
     self.innerParser = InnerParser() 
    } 

    init(innerParser: T) { 
     self.innerParser = innerParser 
    } 
} 

ジェネリック型TInnerParserと同じ型になるという保証はありませんと。確かに、ダウンキャストをTに強制することはできますが、タイプが互換性がない場合は、コードクラッシュが発生します。

残念ながら、この問題の解決策はありません。あなたの最良の選択肢はおそらく、OuterParserインスタンスを作成するための2つのファクトリメソッドを作成することです。

let innerParser = Parser.createParser() // OuterParser<InnerParser> 

let anotherParser = Parser.createParser(AnotherParser()) // OuterParser<AnotherParser> 

enum Parser { 
    static func createParser() -> OuterParser<InnerParser> { 
     return OuterParser(innerParser:InnerParser()) 
    } 
    static func createParser<T>(innerParser:T) -> OuterParser<T> { 
     return OuterParser(innerParser:innerParser) 
    } 
} 

は、我々は、余分な機能を備えたグローバルな名前空間を汚染を避けるために、ここでケースレスの列挙型を使用しています。

これは非常にSwiftyではありませんが、その理由から、パーザをどのように定義するのかについて、あなたのロジックを再考することをお勧めします。

+0

感謝を説明するために。それは少なくとも私にとっては難しいものでした。 – mAu

+0

@mAu助けて嬉しいです:) – Hamish

0

enter image description here

タイプTよりJSONParserTypechild protocolようにあなたはそれを変換することができます

init(innerParser: T = InnerParser() as! T) { 
    self.innerParser = innerParser 
} 
関連する問題