2016-05-26 8 views
1

varletでプロパティを実装すると、実装する構造体にと入力された変数が割り当てられたときの動作が異なります。Swiftプロトコル拡張 `var {get}`オーバーライド実装の `let`

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の動作ですか?

答えて

1

これはコンパイラのバグだと思います。あなたはLetReqオプションの文字列を作る場合は、それが期待どおりに動作:Appleと

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

File a bug

+1

またはhttp://bugs.swift.org – jtbandes

0

動作が正しいと思います。

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

パスがStringタイプないString?

var req: Req! 
req = LetReq() 
req.path 

reqReqのタイプです。だから、req.pathはタイプがString?と名前であることを意味しpath

Reqの拡張子はpath変数のデフォルト変数を持っています。だからreq.pathはその変数を参照しないでくださいLetReqpath

0

それは漠然としています...しかし、私はバグに賭けるでしょう。

少なくとも現在の実装では(swiftc 2.2);

  1. スウィフトでは、異なる戻りタイプのオーバーロードがサポートされています。
  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で財産の過負荷を防止した理由と同じ理由で。だから、それは私の意見ではバグです。

関連する問題