协议声明定义了新的独立类型。虽然它们的行为确实与类、枚举和结构不同,但它们可以充当变量或属性的类型(前提是没有关联的类型约束,但坚持下去)。比如
protocol MyProtocol {}
let myConst: MyProtocol // myConst has type `MyProtocol`
在带有泛型 where 子句的协议扩展中,有两种不同的方式来约束所讨论的泛型类型:使用 :_ 或 ==。两者是有区别的。
使用:_
冒号表示泛型类型与指定的类型或协议匹配。它可以读作“继承自”或“符合”。例如,扩展中指定的任何内容仅适用于关联类型符合 Equatable 或继承自 SomeClass
protocol AnotherProtocol {
associatedtype MyType
}
class SomeClass {}
extension AnotherProtocol where MyType: SomeClass {}
extension AnotherProtocol where MyType: Equatable {}
==的使用
泛型 where 子句中的 == 运算符指定泛型类型是完全指定的类型,而不是其他类型。下面的代码给出了编译时错误
class CustomType {}
class CustomTypeII: CustomType {}
class MyClass: AnotherProtocol { typealias MyType = CustomTypeII }
extension AnotherProtocol where MyType == CustomType {
func myFunc() {}
}
let instance = MyClass()
instance.myFunc() // Error: `CustomTypeII` is not the same type as `CustomType`
== 运算符不能用于将泛型类型限制为具有关联类型的协议。编译器会抱怨协议有关联的类型要求。
protocol ThirdProtocol {}
extension ThirdProtocol where Self == AnotherProtocol {} // Error: `AnotherProtocol` has associated type requirements
本质上,规范是模棱两可的:没有单一的AnotherProtocol 类型,就像没有单一的Array 类型一样。协议中的关联类型的行为类似于泛型类型的泛型参数。在这里,需要使用冒号来指定泛型类型“是”AnotherProtocol 类型(不透明类型源于需要指定具有关联类型约束的协议的特定“类型”,但这超出了问题)。
您的扩展程序
Array 的扩展仅适用于其元素为符合协议类型P 的某种类型的数组实例,不适用于其元素为P 类型的数组。不符合自身的协议类似于不从自身继承的类。
这是一个旧线程,但希望这会有所帮助。