web-dev-qa-db-ja.com

Swift「where self」節を含むプロトコル

プロトコル拡張を使用したこの構文に加えて:

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

...プロトコル自体で同じwhere句を使用できることを偶然発見しました。

protocol P where Self : UIView {}

これはnotが汎用プロトコルを制約するwhere句と同じであり、not自体がPを汎用プロトコルにすることに注意してください。

私の実験では、ここで使用できるのはコロンのみであり、コロンの後のものはクラスまたはプロトコル(汎用の場合もある)でなければならないことを示しているようです。

私は好奇心が強くなりました:これはどのように私の通知を逃れましたか?それで、私はそれがいつ起こったかの証拠を探しに行きました。 In Swift 3.0、前者の構文は合法ですが、not後者。InSwift 3.3、両方とも合法です。シンタックスはSwift 3.2のように静かに導入されたにちがいありません。リリースノートに何も見つからないため、「静かに」と言います。

2番目の構文は何ですか?表示されているように、他のタイプがこのプロトコルを採用できないようにするための便利な方法ですか? Swiftヘッダーはそれを利用していないようです。

21
matt

プロトコル宣言にスーパークラス制約を設定する機能(つまり、protocol P where Self : Cここで、Cはクラスのタイプです)は、
SE-0156 、および機能が実装されるまで構文はSwift 4.xで拒否されました。この機能を=で使用しようとしていますSwift 4.x 誤ったコンパイルとクラッシュを引き起こす可能性があります 、したがって、Swift 5。

Swift 5(Xcode 10.2)の機能には 現在実装済み があります。 リリースノート から:

プロトコルは、準拠する型を特定のクラスをサブクラス化する型に制限できるようになりました。 2つの同等の形式がサポートされています。

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

Swift 4.2は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)
21
Hamish