我有一个Class应该提供一个基于集合的随机生成器 由于它是一个随机生成器(next()永远不会返回nil,除非集合为空),我不希望能够将此生成器用作sequenceType(NO'用于'支持以避免无限循环)< / p>
我似乎无法正确获取方法签名。
这是我构建的框架,我已经包含3次尝试及其相应的编译器错误。
public protocol myProtocol {
var name : String { get }
}
internal struct myProtocolStruct: myProtocol {
let name : String
init(name: String) {
self.name = name
}
}
internal struct myGenerator : GeneratorType {
let names : [myProtocol]
init(names: [myProtocol]) {
self.names = names
}
mutating func next() -> myProtocol? {
return names.first
}
}
public class myClass {
private var items : [myProtocol]
public init() {
let names = ["0", "1", "2"]
items = names.map{ myProtocolStruct(name: $0) }
}
public func generate0() -> GeneratorType { // error: protocol 'GeneratorType' can only be used as a generic constraint because it has Self or associated type requirements
let x = myGenerator(names: items)
return x
}
public func generate1<C: GeneratorType where C.Element == myProtocol>() -> C {
let x = myGenerator(names: items)
return x // error: 'myGenerator' is not convertible to 'C'
}
public func generate2<C: GeneratorType where C.Element: myProtocol>() -> C {
let x = myGenerator(names: items)
return x // error: 'myGenerator' is not convertible to 'C'
}
}
答案 0 :(得分:3)
您可以使用GeneratorOf
:
/// A type-erased generator.
///
/// The generator for `SequenceOf<T>`. Forwards operations to an
/// arbitrary underlying generator with the same `Element` type,
/// hiding the specifics of the underlying generator type.
///
/// See also: `SequenceOf<T>`.
struct GeneratorOf<T> : GeneratorType, SequenceType { ... }
GeneratorOf
可以从另一个生成器创建(需要
不公开):
public func generate() -> GeneratorOf<myProtocol> {
return GeneratorOf(myGenerator(names: items))
}
GeneratorOf
也可以直接从代表next()
函数的闭包中创建:
public func generate() -> GeneratorOf<myProtocol> {
var genItems = self.items // capture the items for use in the closure
return GeneratorOf {
// Return next element, this is just an example which
// returns and removes the first element from the array:
return genItems.count > 0 ? genItems.removeAtIndex(0) : nil
}
}
如果要返回不符合的生成器
SequenceType
然后你可以定义一个稍微修改的包装器
How is a type-erased generic wrapper implemented?:
public struct GeneratorOnlyOf<T> : GeneratorType {
private let _next:() -> T?
init(_ nextElement: () -> T?) {
_next = nextElement
}
init<G : GeneratorType where G.Element == T>(var _ base: G) {
_next = { base.next() }
}
public mutating func next() -> T? {
return _next()
}
}
然后将GeneratorOf
替换为GeneratorOnlyOf
:
public func generate() -> GeneratorOnlyOf<myProtocol> {
return GeneratorOnlyOf(myGenerator(names: items))
}
或者您可以(正如您在评论中指出的那样)定义自己的 非通用协议:
public protocol MyProtocolGenerator {
mutating func next() -> myProtocol?
}
使您的内部生成器符合该协议:
internal struct myGenerator : MyProtocolGenerator { ... }
然后从generate()
方法返回:
public class myClass {
// ...
public func generate() -> MyProtocolGenerator {
return myGenerator(names: items)
}
}
(旧答案:) generate()
方法返回具体的生成器类型,而不是
协议:
func generate() -> myGenerator {
let x = myGenerator(names: items)
return x
}
比较内置Swift类型的生成器,例如
struct Array<T> : MutableCollectionType, Sliceable {
// ...
func generate() -> IndexingGenerator<[T]>
// ...
}
或
struct Dictionary<Key : Hashable, Value> : CollectionType, DictionaryLiteralConvertible {
// ...
func generate() -> DictionaryGenerator<Key, Value>
// ...
}