Swift 2.0:创建符合通用协议的对象的集合类型

时间:2015-09-11 00:44:41

标签: swift swift2 swift-protocols

例如:

protocol SomeProtocol {
    typealias T
    func doSomething(something: T)
}
let a = Array<SomeProtocol>()

我想要一个Array,它是一个符合SomeProtocol的对象数组。这在理论上似乎很好,但我得到以下错误信息:

  

不能用作通用约束,因为它包含assosciated   类型要求。

我认为这是有道理的,毕竟数组是一个通用的结构,所以编译器无法弄清楚SomeProtocol和{{1}的实际类型是什么是通用的。

所以我的问题是 - 我觉得我应该能够拥有一个符合Array的对象数组 - 这在Swift 2.0中是否可能?我是否以错误的方式思考这个问题?

2 个答案:

答案 0 :(得分:3)

出现此错误消息的原因是,如果您的Array声明有效,则会出现以下问题:

protocol SomeProtocol {
    typealias T
    func doSomething(something: T)
}
// has already some values
let a: Array<SomeProtocol> = [...]

// what type should be passed as parameter?
// the type of T in SomeProtocol is not defined
a[0].doSomething(...)

作为解决方法,您可以为任何类型的SomeProtocol创建通用包装器结构,以便您可以指定T的类型(如Swift标准库AnyGenerator,AnySequence,...)。 / p>

struct AnySomeProtocol<T>: SomeProtocol {
    let _doSomething: T -> ()
    // can only be initialized with a value of type SomeProtocol
    init<Base: SomeProtocol where Base.T == T>(_ base: Base) {
        _doSomething = base.doSomething
    }
    func doSomething(something: T) {
        _doSomething(something)
    }
}

现在您使用类型[AnySomeProtocol<T>]的数组(将T替换为您想要的任何类型),然后在追加元素之前将其转换为AnySomeProtocol

var array = [AnySomeProtocol<String>]()
array.append(AnySomeProtocol(someType))

// doSomething can only be called with a string 
array[0].doSomething("a string")

答案 1 :(得分:2)

不,现在在Swift 2中是不可能的。在指定泛型参数之前,不能使用泛型类型。对于泛型类,结构和枚举,可以在使用它们的同时指定它们的泛型参数。例如,可以像这样使用数组:

let anArray: [String]

Array用作变量类型时,String的通用参数指定给Array

但是,通用协议(具有关联类型的协议,名为typealias)只能在具体类型符合它时指定其关联类型。当您使用通用协议作为变量类型(如泛型类,结构或枚举)时,无法提供关联类型。