带有 "where Self"子句的 Swift 协议(protocol)

标签 swift where swift-protocols

除了这个带有协议(protocol)扩展的语法之外:

protocol P {}
extension P where Self : UIView {}

...我偶然发现您可以在协议(protocol)本身上使用相同的 where 子句:

protocol P where Self : UIView {}

请注意,这与约束通用协议(protocol)的 where 子句相同,并且不会本身使 P 成为通用协议(protocol)。

我的实验似乎表明,这里只能使用冒号,冒号后面的东西必须是类或协议(protocol)(可能是通用的)。

我开始好奇:这怎么能逃过我的注意?所以我去寻找它何时出现的证据。在 Swift 3.0 中,前一种语法是合法的,但不是后者。在 Swift 3.3 中,两者都是合法的。所以后一种语法一定是在 Swift 3.2 之类的东西中悄悄引入的。我说“悄悄地”是因为我在发行说明中找不到任何相关内容。

第二个语法是做什么用的?看起来,它只是一种确保没有其他类型可以采用此协议(protocol)的便捷方式吗? Swift header 似乎没有使用它。

最佳答案

将父类(super class)约束放在协议(protocol)声明上的能力(即能够定义 protocol P where Self : C 其中 C 是类的类型)是
SE-0156 的过早后果,并且在实现该功能之前,该语法应该在 Swift 4.x 中被拒绝。尝试在 Swift 4.x 中使用此功能 can cause miscompilation and crashes ,所以在 Swift 5 之前我会避免使用它。

在 Swift 5 (Xcode 10.2) 中,该功能具有 now been implemented .来自 the release notes :

Protocols can now constrain their conforming types to those that subclass a given class. Two equivalent forms are supported:

protocol MyView: UIView { /*...*/ }
protocol MyView where Self: UIView { /*...*/ } 

Swift 4.2 accepted the second form, but it wasn’t fully implemented and could sometimes crash at compile time or runtime. (SR-5581) (38077232)

此语法在 MyView 上放置了一个父类(super class)约束,它将符合类型限制为继承自(或属于)UIView 的类型。此外,MyView 的用法在语义上等同于存在类(例如 UIView & MyView),因为您可以访问类的成员和协议(protocol)的要求值(value)。

例如,扩展发行说明的示例:

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)

关于带有 "where Self"子句的 Swift 协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50913244/

相关文章:

ios - 删除 UILongPressGesture 默认 Action

android - ios swift SHA1加密

ios - (iOS) iBeacon 唤醒如何工作?

swift - 如何列出对象符合的协议(protocol)?

swift - 如何在 Swift 4 中使用 #selector() 处理 @objc 推理弃用?

mysql - MySQL 的 'where col in (list)' 替代方案

linq - LINQ Where子句中的if条件

sql - 过滤 JOIN : WHERE vs. ON

Swift 协议(protocol)和扩展,如果存在,我需要调用实例方法

swift - 为什么这不像我期望(希望)的那样表现?