代码之家  ›  专栏  ›  技术社区  ›  matt

带有“where self”条款的swift协议

  •  21
  • matt  · 技术社区  · 6 年前

    除了此语法和协议扩展之外:

    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头文件似乎没有任何用处。

    1 回复  |  直到 6 年前
        1
  •  21
  •   Hamish    5 年前

    在协议声明上设置超类约束的能力(即,能够定义 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 :

    协议现在可以将它们的一致类型限制为 将给定类的子类化。支持两种等效形式:

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

    swift 4.2接受了第二种形式,但没有完全实现 有时会在编译时或运行时崩溃。( SR-5581 ) (38077232)

    此语法在 MyView 它将一致类型限制为继承自(或存在于)的类型 UIView . 此外,使用 MyVIEW 在语义上等同于类的存在性(例如 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)