1

と を使用したプロパティの実装は、実装する構造体が as 型の変数に割り当てられている場合、動作が異なりvarます。letprotocol

protocol Req {
  var path: String? { get }
}
extension Req {
  var path: String? { return "Req" }
}

struct LetReq: Req {
  let path = "LetReq"
}
struct VarReq: Req {
  var path: String? { return "VarReq" }
}

var req: Req!

req = VarReq()
req.path // prints "VarReq"

req = LetReq()
req.path // prints "Req" not "LetReq" which seems very awkward.

これは Swift の設計された動作ですか?

4

3 に答える 3

1

これはコンパイラのバグだと思います。LetReqオプションの文字列を作成すると、期待どおりに機能します。

struct LetReq: Req {
    let path: String? = "LetReq"
}

Appleにバグを報告します。

于 2016-05-26T02:20:56.963 に答える
0

漠然としています...しかし、私はバグに賭けます。

少なくとも現在の実装では ( swiftc2.2);

  1. Swift は、異なる戻り値の型のみによるメソッドのオーバーロードをサポートしています。
  2. ただし、プロパティではなくメソッドのみです。
  3. したがって、すべてのプロパティには異なる名前を付ける必要があります。

これで証明できる。

struct AA {
    func a() -> String { return "" }
    func a() -> String? { return "" }
    var b: String { return "" }
    var b: String? { return "" } // Error: Invalid redeclaraion of `b`.
}

とにかく、コンパイラはプロトコル拡張によるこの再宣言をチェックしていないようです。したがって、LetReqインスタンスは実際には 2 つのプロパティを提供します。

var path: String { get }
var path: String? { get }

これで確認できます。

print(LetReq().path as String?)    // prints `Optional("Req")`.
print(LetReq().path as String)     // prints `LetReq`.

この種のプロパティのオーバーロードは、コンパイラで防止する必要があると思います。でプロパティのオーバーロードを防止したのと同じ理由でstruct AA。だから、それは私の意見ではバグです。

于 2016-05-27T06:00:03.630 に答える