非オプションによるSwiftプロトコルのオプションの適合性

Aug 18 2020

オプションのプロパティを持つプロトコルがあります。

このプロトコルに準拠するほとんどのタイプには、一致するオプションのプロパティがあります。ただし、同じタイプと名前のオプションではないプロパティがあります。

protocol SomeProtocol {
    var foo: Int? { get }
}

struct StructA: SomeProtocol {
    let foo: Int?
}

struct StructB: SomeProtocol {
    let foo: Int // Type 'StructB' does not conform to protocol 'SomeProtocol'
}

Xcodeの「修正-プロトコルスタブを追加しますか?」を押します。ボタンはプロパティのオプションバージョンを追加しますが、構造には無効な重複変数名が含まれるようになりました。

struct StructB: SomeProtocol {
    let foo: Int
    var foo: Int? { return foo } // Invalid redeclaration of 'foo'
}

{ get }のみの場合、私は非オプションのために、この希望「だけの仕事は」いつもあなたは、オプションの戻り値の型を持つ関数に非オプションを返すことができるのと同じように、オプションの制約を満たすことを前提としていました。しかし、明らかにそうではありません。

これは関数でも同じように機能します。プロトコルfunc bar() -> Int?は、を宣言する適合型によって満たされませんfunc bar() -> Int

この問題を回避する方法はありますか?変数の名前を変更したり、中間ゲッターを追加したりしたくありません。

この状況はスイフトのために考慮されましたか?非オプションがオプションのプロトコル変数を満たすことを許可しない理由は何ですか?

回答

pkamb Aug 19 2020 at 00:34

プロトコルがオプションを返すデフォルトの実装を提供する場合:

protocol SomeProtocol {
    var foo: Int? { get }
}

extension SomeProtocol {
    var foo: Int? { return nil }
}

プロトコル準拠の型は、変数/関数のオーバーライドする非オプションバージョンを提供できます。

struct StructB: SomeProtocol {
    let foo: Int
}

私はこれがSwiftEvolutionフォーラムで議論されているのを見つけました:

一見、オプション以外の型でプロトコル要件を満たすことができるルールがあると思いましたが、エラーになりました。さらに調査した後、オプションではないバージョンで要件を「オーバーライド」するために、デフォルトの実装が存在する必要があることに気付きました。

https://forums.swift.org/t/how-does-this-rule-work-in-regard-of-ambiguity/19448

このSwiftチームは、オプション以外の型がオプション値プロトコルを満たすことを許可することについても説明します。

失敗可能なinitのように、オプションではない型でプロトコル要件を満たすことを許可することは意味がありますか?(おそらく、いくつかの暗黙のオプションのプロモーションがあります。)

うん、完全に!これにより既存のコードの動作が変わる部分を除いて、非常に注意する必要があります。これは[SR-522]の一部と見なされますプロトコル関数は共変リターンを持つことはできません

これはここでスタックオーバーフローで追跡されます:

プロトコルのget-onlyプロパティ要件が、準拠するプロパティでは満たされないのはなぜですか?