例如:
protocol SomeProtocol {
typealias T
func doSomething(something: T)
}
let a = Array<SomeProtocol>()
我想要一个Array,它是一个符合SomeProtocol
的对象数组。这在理论上似乎很好,但我得到以下错误信息:
不能用作通用约束,因为它包含assosciated 类型要求。
我认为这是有道理的,毕竟数组是一个通用的结构,所以编译器无法弄清楚SomeProtocol
和{{1}的实际类型是什么是通用的。
所以我的问题是 - 我觉得我应该能够拥有一个符合Array
的对象数组 - 这在Swift 2.0中是否可能?我是否以错误的方式思考这个问题?
答案 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)只能在具体类型符合它时指定其关联类型。当您使用通用协议作为变量类型(如泛型类,结构或枚举)时,无法提供关联类型。