2016-05-26 123 views
5

我已經創建了我的自定義序列類型,並且我希望函數接受任何種類的序列作爲參數。 (我想用就可以了兩套,我的序列類型)Swift:作爲函數參數的任何類型的序列

事情是這樣的:

private func _addToCurrentTileset(tilesToAdd tiles: SequenceType) 

有什麼辦法我該怎麼辦呢?

它似乎相對簡單,但我不知道怎麼弄出來。 Swift工具鏈告訴我: Protocol 'SequenceType' can only be used as a generic constraint because it has Self or associated type requirements,我不知道如何創建一個符合SequenceType和自身要求的協議。

我可以消除與associatedType要求,但不能自我:

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

現在如果說我能消除自我要求,則已經有這樣的協議定義其他collectionType實體,如數組,集合將不符合它。

參考: 我自定義序列枚舉類型的所有子類中定義爲:

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

您可以使用類型的橡皮擦AnySequence爲:

A型擦除序列。

將操作轉移到具有相同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 
} 
相關問題