正如Thomas所指出的,您可以通过根本不提供类型来声明变量(或者可以将其显式地指定为type
Printer<Int>。但这是对为什么不能拥有
Printable协议类型的解释。
您不能将协议类型与常规协议一样对待,也不能将它们声明为独立变量类型。要考虑原因,请考虑这种情况。假设您声明了一个协议,用于存储任意类型,然后将其取回:
// a general protocol that allows for storing and retrieving// a specific type (as defined by a Stored typealiasprotocol StoringType { typealias Stored init(_ value: Stored) func getStored() -> Stored}// An implementation that stores Intsstruct IntStorer: StoringType { typealias Stored = Int private let _stored: Int init(_ value: Int) { _stored = value } func getStored() -> Int { return _stored }}// An implementation that stores Stringsstruct StringStorer: StoringType { typealias Stored = String private let _stored: String init(_ value: String) { _stored = value } func getStored() -> String { return _stored }}let intStorer = IntStorer(5)intStorer.getStored() // returns 5let stringStorer = StringStorer("five")stringStorer.getStored() // returns "five"好的,到目前为止很好。
现在,将变量的类型设为类型实现的协议而不是实际类型的主要原因是,您可以将所有都符合该协议的不同类型的对象分配给同一变量,并获得多态性运行时的行为取决于对象实际是什么。
但是,如果协议具有关联的类型,则无法执行此操作。以下代码在实践中将如何工作?
// as you've seen this won't compile because// StoringType has an associated type.// randomly assign either a string or int storer to someStorer:var someStorer: StoringType = arc4random()%2 == 0 ? intStorer : stringStorerlet x = someStorer.getStored()
在上面的代码中,类型
x是什么?安
Int?还是一个
String?在Swift中,所有类型都必须在编译时固定。函数无法根据运行时确定的因素动态地从一种类型返回到另一种类型。
相反,您只能将其
StoredType用作通用约束。假设您要打印出任何类型的存储类型。您可以编写如下函数:
func printStoredValue<S: StoringType>(storer: S) { let x = storer.getStored() println(x)}printStoredValue(intStorer)printStoredValue(stringStorer)可以,因为在编译时,好像编译器写出了两个版本
printStoredValue:一个用于
Ints,一个用于
Strings。在这两个版本中,
x已知是特定类型的。



