Swift 带有 "where Self" 子句的协议
Swift protocol with "where Self" clause
除了这个带有协议扩展的语法:
protocol P {}
extension P where Self : UIView {}
...我偶然发现您可以在协议本身上使用相同的 where 子句:
protocol P where Self : UIView {}
请注意,这 not 与约束通用协议的 where 子句相同,并且 not 本身是否使 P 成为通用协议.
我的实验似乎表明这里只能使用冒号,冒号后面的东西必须是class或协议(可能是通用的)。
我很好奇:这怎么能逃过我的注意?所以我去寻找它何时出现的证据。在 Swift 3.0 中,前一种语法是合法的,但 不是 后者。在 Swift 3.3 中,两者都是合法的。所以后一种语法一定是在 Swift 3.2 之类的东西中悄悄引入的。我说 "quietly" 是因为我在发行说明中找不到任何相关信息。
第二种语法是做什么用的?看起来,它只是一种确保没有其他类型可以采用此协议的便捷方式吗? Swift headers 似乎没有任何用处。
对协议声明施加超级class约束的能力(即能够定义protocol P where Self : C
,其中C
是class的类型)是
SE-0156, and the syntax should have been rejected in Swift 4.x until the feature was implemented. Attempting to use this feature in Swift 4.x 的过早后果,所以我会在 Swift 5.
之前避免使用它
在 Swift 5 (Xcode 10.2) 中,特征有 now been implemented. From 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
上放置了一个 superclass 约束,它将符合类型限制为继承自(或属于)UIView
的类型。此外,MyView
的用法在语义上等同于 class 存在(例如 UIView & MyView
),因为您可以访问 class 的成员和协议的要求值。
例如,扩展发行说明的示例:
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)
除了这个带有协议扩展的语法:
protocol P {}
extension P where Self : UIView {}
...我偶然发现您可以在协议本身上使用相同的 where 子句:
protocol P where Self : UIView {}
请注意,这 not 与约束通用协议的 where 子句相同,并且 not 本身是否使 P 成为通用协议.
我的实验似乎表明这里只能使用冒号,冒号后面的东西必须是class或协议(可能是通用的)。
我很好奇:这怎么能逃过我的注意?所以我去寻找它何时出现的证据。在 Swift 3.0 中,前一种语法是合法的,但 不是 后者。在 Swift 3.3 中,两者都是合法的。所以后一种语法一定是在 Swift 3.2 之类的东西中悄悄引入的。我说 "quietly" 是因为我在发行说明中找不到任何相关信息。
第二种语法是做什么用的?看起来,它只是一种确保没有其他类型可以采用此协议的便捷方式吗? Swift headers 似乎没有任何用处。
对协议声明施加超级class约束的能力(即能够定义protocol P where Self : C
,其中C
是class的类型)是
SE-0156, and the syntax should have been rejected in Swift 4.x until the feature was implemented. Attempting to use this feature in Swift 4.x
在 Swift 5 (Xcode 10.2) 中,特征有 now been implemented. From 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
上放置了一个 superclass 约束,它将符合类型限制为继承自(或属于)UIView
的类型。此外,MyView
的用法在语义上等同于 class 存在(例如 UIView & MyView
),因为您可以访问 class 的成员和协议的要求值。
例如,扩展发行说明的示例:
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)