タイプT
は、クラスによって定義されていません。クラスを使用するコードで定義されています。したがって、クラス内で何かを行う前に(インスタンスまたは静的レベルで)定義されます。したがって、InnerParser
をT
に割り当てることはできません。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
}
}
ジェネリック型T
がInnerParser
と同じ型になるという保証はありませんと。確かに、ダウンキャストを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ではありませんが、その理由から、パーザをどのように定義するのかについて、あなたのロジックを再考することをお勧めします。
感謝を説明するために。それは少なくとも私にとっては難しいものでした。 – mAu
@mAu助けて嬉しいです:) – Hamish