2016-05-26 16 views
5

Utworzony został mój niestandardowy typ sekwencji i chcę, aby funkcja akceptowała dowolny typ sekwencji jako parametr. (Chcę użyć obu zestawów, a moje typy sekwencji na nim)Swift: Dowolny rodzaj sekwencji jako parametr funkcji

coś takiego:

private func _addToCurrentTileset(tilesToAdd tiles: SequenceType) 

Czy istnieje jakiś sposób, w jaki sposób mogę to zrobić?

Wydaje się stosunkowo proste, ale nie mogę tego jakoś rozgryźć. Swift Toolchain mówi: Protocol 'SequenceType' can only be used as a generic constraint because it has Self or associated type requirements, i nie wiem, jak utworzyć protokół, który będzie zgodny z SequenceType i wymogiem Self z niego.

mogę wyeliminować wymóg associatedType z, ale nie siebie:

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

Teraz mogę powiedzieć, czy wyeliminowanie wymogu samodzielne, potem już z takiej definicji protokół innymi podmiotami collectionType takich tablic, zestawy nie będą zgodne z to.

referencyjny: moje niestandardowe sekwencje są wszystkie podklasy rodzaju enumeratora zdefiniowany jako:

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

Odpowiedz

6

Kompilator mówi ci odpowiedź: „«Sequence»protokół może być używany tylko jako ogólne ograniczenie ponieważ ma Jaźni lub powiązanych wymagań typu”.

Można więc zrobić to z rodzajowych:

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

To pozwoli Ci przejść w dowolnym betonowej typu zgodnym z Sequence do swojej funkcji. Swift określi konkretny typ, umożliwiając przekazanie sekwencji bez utraty informacji o typie.

Jeśli chcesz ograniczyć typ elementu w sekwencji dla danego protokołu, można zrobić:

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

Lub typu beton

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

Jeśli don” t dbasz o konkretny typ samej sekwencji (przydatne do ich mieszania, a w większości przypadków do ich przechowywania), a następnie Anton's answer obdarzyła Cię wersją skasowaną typem Sequence.

+0

wielkie dzięki, naprawdę zależy mi na typie elementów wewnątrz sekwencji, czy jest jakiś sposób na ograniczenie rodzaju elementów wewnątrz? coś takiego: ambientlight

+1

@ambientlight Oczywiście, możesz zrobić '' jeśli 'TileID' jest protokołem lub' == TileID' jeśli jest to konkretny typ – Hamish

4

Można użyć typu gumki AnySequence za to:

Sekwencja typu skasowane.

Przekazuje operacje do dowolnej sekwencji bazowej mającej ten sam typ Element, ukrywając specyfikację podstawowej SequenceType.

Np. jeśli będziesz musiał przechowywać płytki jako właściwość wewnętrzną lub w jakiś sposób użyć jej typu betonu w strukturze obiektu, to byłaby to właściwa droga.

Jeśli po prostu musisz mieć możliwość użycia sekwencji bez konieczności przechowywania (na przykład po prostu map), możesz po prostu użyć generycznych (jak sugeruje @ originaluser2). Na przykład. może skończyć się z czymś takim:

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 
} 
Powiązane problemy