2016-05-26 16 views
5

Ho creato il mio tipo di sequenza personalizzato e voglio che la funzione accetti qualsiasi tipo di sequenza come parametro. (Voglio usare entrambi i set, i miei tipi di sequenze su di esso)Swift: Qualsiasi tipo di sequenza come parametro di funzione

Qualcosa di simile a questo:

private func _addToCurrentTileset(tilesToAdd tiles: SequenceType) 

C'è un modo come posso farlo?

Sembra relativamente semplice, ma non riesco a capirlo in qualche modo. La toolchain rapida mi dice: Protocol 'SequenceType' can only be used as a generic constraint because it has Self or associated type requirements, e non so come creare un protocollo che si conformerà a SequenceType e il requisito di Sé da esso.

posso eliminare il requisito associatedType con, ma non Auto:

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

Ora, se dico posso eliminare il requisito di sé, quindi già con tale definizione del protocollo di altri enti collectionType come gli array, insiemi non saranno conformi alle esso.

Riferimento: mie sequenze personalizzate vengono tutte le sottoclassi di tipo enumeratore definite come:

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

risposta

6

Il compilatore si sta dicendo la risposta: " 'Sequence' protocollo può essere utilizzato solo come un vincolo generico perché ha Sé o requisiti di tipo associato".

Si può quindi fare questo con i generici:

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

Questo vi permetterà di passare in qualsiasi tipo di cemento che è conforme alla Sequence nella vostra funzione. Swift dedurrà il tipo concreto, consentendo di passare la sequenza senza perdere informazioni sul tipo.

Se si desidera limitare il tipo di elemento nella sequenza di un determinato protocollo, si può fare:

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

O per un tipo concreto:

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

Se don' t attenzione al tipo concreto della sequenza stessa (utile per mescolarli insieme e nella maggior parte dei casi memorizzarli), quindi Anton's answer ti ha coperto con la versione cancellata dal tipo di Sequence.

+0

grazie mille, mi interessa davvero il tipo di elementi all'interno della sequenza, c'è un modo per limitare un tipo di elementi all'interno? qualcosa come: ambientlight

+1

@ambientlight Sure, si può fare '' se 'TileID' è un protocollo o' == TileID' se è un tipo concreto – Hamish

4

È possibile utilizzare tipo-gomma AnySequence per questo:

Una sequenza di tipo-cancellati.

Inoltra le operazioni a una sequenza sottostante arbitraria con lo stesso tipo Element, nascondendo le specifiche del sottostante SequenceType.

E.g. se è necessario memorizzare le tessere come proprietà interne o in qualche modo usare il suo tipo concreto nella struttura dell'oggetto, allora quella sarebbe la strada da percorrere.

Se devi semplicemente essere in grado di utilizzare la sequenza senza doverlo memorizzare (ad esempio solo map su di esso), puoi semplicemente utilizzare i generici (come suggerisce @ originaluser2). Per esempio. si potrebbe finire con qualcosa di simile:

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 
}