Swift协议带有"where self"子句

mat*_*att 22 where swift swift-protocols

除了具有协议扩展的语法之外:

protocol P {}
extension P where Self : UIView {}
Run Code Online (Sandbox Code Playgroud)

...我偶然发现你可以在协议本身使用相同的where子句:

protocol P where Self : UIView {}
Run Code Online (Sandbox Code Playgroud)

请注意,这是不一样的where子句限制一个通用的协议,并没有自己做P上的通用协议.

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

我变得很好奇:这是怎么逃避我的注意的?所以我去寻找它何时出现的证据.在Swift 3.0中,前一种语法是合法的,但不是后者.在Swift 3.3中,两者都是合法的.所以后一种语法必须在Swift 3.2之类的东西中悄然引入.我说"悄悄地",因为我在发行说明中找不到任何关于它的内容.

第二种语法是什么?它看起来只是一种方便的方法来确保没有其他类型可以采用这个协议吗?Swift标头似乎没有使用它.

Ham*_*ish 23

的能力穿上协议声明超约束(即,能够定义protocol P where Self : C,其中C一类的类型)是过早的后果
SE-0156,和语法应该被拒绝,直到功能被实现.它目前(在Swift 4.x中)周围有很多锋利的边缘,所以我现在暂时避开它 - 请在此处查看我的答案以获取更多信息.

该功能本身最近才为Swift 5 实现(您可以在主快照中自行试用),允许您使用以下语法:

protocol MyView: UIView { /*...*/ }
protocol MyView where Self: UIView { /*...*/ } 
Run Code Online (Sandbox Code Playgroud)

或者,更为一致:

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)
Run Code Online (Sandbox Code Playgroud)

为了放置超类约束MyView,将符合类型限制为从(或是)继承的类型UIView.此外,使用在MyView语义上等同于存在类(例如UIView & MyView),因为您可以访问类的成员和协议对值的要求.

例如,使用您的protocol P where Self : C示例:

protocol MyView: UIView { /*...*/ }
protocol MyView where Self: UIView { /*...*/ } 
Run Code Online (Sandbox Code Playgroud)