2016-05-26 51 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 
} 
相关问题