2

例如:

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

我想要一个数组,它是一个符合SomeProtocol. 这在理论上似乎很好,但我收到以下错误消息:

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

而且我想这是有道理的,毕竟 Array 也是一个泛型结构,所以编译器将无法弄清楚两者实际上是什么类型,SomeProtocol并且Array都是泛型的。

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

4

2 回答 2

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、...中)。

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")
于 2015-09-11T21:23:46.380 回答
2

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

let anArray: [String]

这里的泛型参数Array被指定为StringArray用作变量的类型时。

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

于 2015-09-11T02:40:12.493 回答