Swift: Any Kind 序列作为函数参数
Swift: Any Kind of sequence as a function parameter
我已经创建了自定义序列类型,我希望该函数接受任何类型的序列作为参数。 (我想同时使用这两个集合,以及我的序列类型)
像这样:
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 和 Self 要求的协议。
我可以消除 associatedType 要求,但不能消除 Self:
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()
}
}
你可以使用类型橡皮擦AnySequence
:
A type-erased sequence.
Forwards operations to an arbitrary underlying sequence having the same Element
type, hiding the specifics of the underlying SequenceType
.
例如如果您需要将图块存储为内部 属性 或以某种方式在您的对象结构中使用其具体类型,那么这就是方法。
如果您只需要能够使用必须存储它的序列 w/o(例如仅 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
}
编译器告诉你答案:“协议'Sequence'只能用作作为通用约束,因为它具有Self或关联类型要求”。
因此您可以使用泛型来做到这一点:
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 {
...
}
如果您不关心序列本身的具体类型(对于将它们混合在一起以及在大多数情况下存储它们很有用),那么 已经为您提供了类型擦除版本Sequence
.
我已经创建了自定义序列类型,我希望该函数接受任何类型的序列作为参数。 (我想同时使用这两个集合,以及我的序列类型)
像这样:
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 和 Self 要求的协议。
我可以消除 associatedType 要求,但不能消除 Self:
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()
}
}
你可以使用类型橡皮擦AnySequence
:
A type-erased sequence.
Forwards operations to an arbitrary underlying sequence having the same
Element
type, hiding the specifics of the underlyingSequenceType
.
例如如果您需要将图块存储为内部 属性 或以某种方式在您的对象结构中使用其具体类型,那么这就是方法。
如果您只需要能够使用必须存储它的序列 w/o(例如仅 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
}
编译器告诉你答案:“协议'Sequence'只能用作作为通用约束,因为它具有Self或关联类型要求”。
因此您可以使用泛型来做到这一点:
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 {
...
}
如果您不关心序列本身的具体类型(对于将它们混合在一起以及在大多数情况下存储它们很有用),那么 Sequence
.