除了带有协议扩展的语法外:
protocol P {} extension P where Self : UIView {}
…我偶然发现您可以在协议本身上使用相同的where子句:
protocol P where Self : UIView {}
请注意,这是 不 一样的where子句限制一个通用的协议,并 没有 自己做P上的通用协议。
我的实验似乎表明,此处只能使用冒号,并且冒号后面的内容必须是类或协议(可能是通用的)。
我很好奇:这是怎么逃避我的注意的?所以我去寻找它何时出现的证据。在Swift 3.0中,前一种语法是合法的,但后者 则不 合法。在Swift 3.3中,两者均合法。因此,后一种语法必须已在Swift 3.2之类的工具中悄悄引入。我之所以说“安静”是因为在发行说明中找不到任何有关它的信息。
第二种语法是什么?看来,这是否是确保没有其他类型可以采用此协议的便捷方法?Swift标头似乎没有使用它。
SE-0156的过早结果就是能够将超类约束放在协议声明上(也就是说,能够定义类的类型protocol P where Self : C在哪里C),并且该语法在Swift 4.x中应该被拒绝,直到该功能被发布为止。已实施。尝试在Swift 4.x中使用此功能可能会导致错误编译和崩溃,因此在Swift 5之前我将避免使用它。
protocol P where Self : C
C
在Swift 5(Xcode10.2)中,该功能现已实现。从发行说明中:
协议现在可以将其符合类型限制为子类化给定类。支持两种等效形式: protocol MyView: UIView { /*...*/ } protocol MyView where Self: UIView { /*...*/ } Swift 4.2接受了第二种形式,但尚未完全实现,有时可能在编译时或运行时崩溃。(SR-5581)(38077232)
协议现在可以将其符合类型限制为子类化给定类。支持两种等效形式:
protocol MyView: UIView { /*...*/ } protocol MyView where Self: UIView { /*...*/ }
Swift 4.2接受了第二种形式,但尚未完全实现,有时可能在编译时或运行时崩溃。(SR-5581)(38077232)
此语法MyView施加了一个超类约束,该约束将符合类型限制为从(或作为)继承的类型UIView。此外,的用法在MyView语义上等同于类存在类(例如UIView& MyView),因为您可以访问该类的成员以及该值的协议要求。
MyView
UIView
UIView& MyView
例如,扩展发行说明的示例:
protocol MyView : UIView { var foo: Int { get } } class C : MyView {} // error: 'P' requires that 'C' inherit from 'UIView' class CustomView : UIView, MyView { var foo: Int = 0 } // ... let myView: MyView = CustomView(frame: .zero) // We can access both `UIView` members on a `MyView` value print(myView.backgroundColor as Any) // ... and `MyView` members as usual. print(myView.foo)