Swift protocol with "where Self" clause
The ability to put superclass constraints on protocols declarations (that is, being able to define protocol P where Self : C
where C
is the type of a class) was a premature consequence of
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 can cause miscompilation and crashes, so I would avoid using it until Swift 5.
In Swift 5 (Xcode 10.2) the feature has 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)
This syntax places a superclass constraint on MyView
which restricts conforming types to those inheriting from (or being) UIView
. In addition, the usage of MyView
is semantically equivalent to a class existential (e.g UIView & MyView
) in that you can access both members of the class and requirements of the protocol on the value.
For example, expanding upon the release notes' example:
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)