1

我有一个类,它应该提供一个基于集合的随机生成器。
由于它是一个随机生成器(next() 永远不会返回 nil,除非集合为空),我不希望能够将此生成器用作 sequenceType(不支持“for in”以避免无限循环)

我似乎无法正确获取方法签名。

这是我构建的框架,我包含了 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'
  }
}
4

1 回答 1

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那么您可以定义对 如何实现类型擦除通用包装器中定义的包装器的轻微修改?

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

然后替换GeneratorOfGeneratorOnlyOf

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>
    // ...
}
于 2015-03-29T20:06:45.023 回答