引用实现具有关联类型的协议的实例

时间:2014-10-14 14:32:58

标签: generics swift

问题

我跟着common pattern by Apple(第4个回复)来解决缺乏通用协议的问题:我试图实现一个GeneratorOf<T> / SequenceOf<T> - 类似的结构,可以保存任何引用实现我的ExampleType协议的实例。由于协议使用关联类型,我不能直接使用它作为变量的类型,需要一个包装器结构。

这个工作正常,直到我遇到一个通用函数。我无法创建一个闭包来转发到这个函数,因此不能像Apple在GeneratorOf<T>中那样完全实现我的包装器结构。

当前状态

这是一个简化但不完整的例子,它在Xcode 6.1 GM 2上编译得很好但缺少通用功能:

protocol ExampleType {

    typealias Element

    func functionWithElement(element: Element)
    func functionWithSequence<S: SequenceType where S.Generator.Element == Element>(sequence: S)
}


struct ExampleOf<T>: ExampleType {

    typealias Element = T

    private let _functionWithElement: (T) -> ()
    // how to declare _functionWithSequence?


    init<E: ExampleType where E.Element == T>(_ base: E) {
        _functionWithElement = { base.functionWithElement($0) }
        // how to assign _functionWithSequence?
    }

    func functionWithElement(element: Element) {
        _functionWithElement(element)
    }

    func functionWithSequence<S: SequenceType where S.Generator.Element == Element>(sequence: S) {
        // how to call _functionWithSequence?
    }
}

天真的方法

这就是应该工作的方式,但在Swift中显然是不可能的。

protocol ExampleType {

    typealias Element

    func functionWithElement(element: Element)
    func functionWithSequence<S: SequenceType where S.Generator.Element == Element>(sequence: S)
}



struct ExampleOf<T>: ExampleType {

    typealias Element = T

    private let _functionWithElement: (T) -> ()
    private let _functionWithSequence: <S: SequenceType where S.Generator.Element == Element>((S) -> ())
    // ERROR: Only syntactic function types can be generic


    init<E: ExampleType where E.Element == T>(_ base: E) {
        _functionWithElement = { base.functionWithElement($0) }
        _functionWithSequence = { base.functionWithSequence($0) }
    }

    func functionWithElement(element: Element) {
        _functionWithElement(element)
    }

    func functionWithSequence<S: SequenceType where S.Generator.Element == Element>(sequence: S) {
        _functionWithSequence(sequence)
    }
}

问题

我如何解决这个限制?
如果只是在包装内,我不介意在这里和那里进行演员表。

1 个答案:

答案 0 :(得分:0)

您所要做的就是用SequenceOf<T>包装参数:

protocol ExampleType {
    typealias Element

    func functionWithElement(element: Element)
    func functionWithSequence<S: SequenceType where S.Generator.Element == Element>(sequence: S)
}

struct ExampleOf<T>: ExampleType {

    private let _functionWithElement: (T) -> ()
    private let _functionWithSequence: (SequenceOf<T>) -> ()

    init<E: ExampleType where E.Element == T>(_ base: E) {
        _functionWithElement = { base.functionWithElement($0) }
        _functionWithSequence = { base.functionWithSequence($0) }
    }

    func functionWithElement(element: T) {
        _functionWithElement(element)
    }

    func functionWithSequence<S: SequenceType where S.Generator.Element == T>(sequence: S) {
        _functionWithSequence(SequenceOf(sequence))
    }
}