2016-05-26 5 views
5

私はカスタムシーケンス型を作成しましたが、この関数は任意の種類のシーケンスをパラメータとして受け入れるようにします。このような(私は両方のセットを使用したい、そしてその上に私のシーケンス型)Swift:任意の種類の関数パラメータとしてのシーケンス

何か:

private func _addToCurrentTileset(tilesToAdd tiles: SequenceType) 

私はそれを行うことができますどのようにどのような方法はありますか?

これは比較的単純なようですが、何とかそれを把握することはできません。スウィフトツールチェインは私に言った: Protocol 'SequenceType' can only be used as a generic constraint because it has Self or associated type requirements、私はそれからSequenceTypeと自己要件に準拠するプロトコルを作成する方法を知らない。

私はセルフでassociatedType要件を排除することはできませんが、私は配列のようなプロトコル定義、他のCollectionTypeはエンティティと、すでに、その後、自己の要求を排除することができると言う場合

protocol EnumerableTileSequence: SequenceType { 
    associatedtype GeneratorType = geoBingAnCore.Generator 
    associatedtype SubSequence: SequenceType = EnumerableTileSequence 
} 

を今、セットはに準拠していますそれ。あなたはそのために、型消しゴムAnySequenceを使用することができます

public class Enumerator<T> { 

    public func nextObject() -> T? { 
     RequiresConcreteImplementation() 
    } 
} 

extension Enumerator { 

    public var allObjects: [T] { 
     return Array(self) 
    } 
} 

extension Enumerator: SequenceType { 

    public func generate() -> Generator<T> { 
     return Generator(enumerator: self) 
    } 
} 

public struct Generator<T>: GeneratorType { 

    let enumerator: Enumerator<T> 
    public mutating func next() -> T? { 
     return enumerator.nextObject() 
    } 
} 

答えて

6

コンパイラはあなたに答え語っている:「それは自己または関連タイプの要件を持っているので、唯一の一般的な制約としてを使用することができます議定書 『配列』を」あなたのようなもので終わるかもしれません。

そのため、ジェネリックでこれを行うことができます。

private func _addToCurrentTileset<T: Sequence>(tilesToAdd tiles: T) { 
    ... 
} 

これは、あなたの関数にSequenceに準拠する任意の具体的なタイプに渡すことができるようになります。 Swiftは具体的な型を推測し、型情報を失うことなくシーケンスを渡すことができます。

あなたが与えられたプロトコルに対する配列の要素の種類を制限したい場合は、あなたが行うことができます:

private func _addToCurrentTileset<T: Sequence>(tilesToAdd tiles: T) where T.Element: SomeProtocol { 
    ... 
} 

やコンクリート型へ:

private func _addToCurrentTileset<T: Sequence>(tilesToAdd tiles: T) where T.Element == SomeConcreteType { 
    ... 
} 

あなたはドンが」シーケンス自体の具体的なタイプ(それらを一緒に混合して保存するのに便利です)を気にするなら、Anton's answerはタイプ消去されたバージョンSequenceでカバーしました。

+0

ありがとう、私は実際にシーケンス内の要素の種類に気をつけていますが、要素の種類を内部に制約するいくつかの方法がありますか? ambientlight

+1

@ambientlight確かに、 '' 'TileID'がプロトコルか' ==具体的なタイプの場合はTileID' – Hamish

4

型消去シーケンス

参考:として 私のカスタムシーケンスは、列挙型のすべてのサブクラスが定義されています。

同じElementタイプを持つ任意の基礎となるシーケンスへの操作を転送し、基になるSequenceTypeの詳細を隠します。

など。内部プロパティとしてタイルを格納する必要がある場合や、何らかの理由でオブジェクトの構造に具体的な型を使用する必要がある場合は、それは行く方法です。

保存する必要のないシーケンスを使用するだけであれば(たとえば、map)、単純にジェネリック(@ originaluser2のように)を使用できます。例えば。

private func _addToCurrentTileset<S: SequenceType where S.Generator.Element == Tile>(tilesToAdd tiles: S) { 
    let typeErasedSequence = AnySequence(tiles) // Type == AnySequence<Tile> 
    let originalSequence = tiles // Type == whatever type that conforms to SequenceType and has Tile as its Generator.Element 
} 
関連する問題