Implementing property with var
and let
behaves differently when the implementing struct is assigned to a variable typed as protocol
.
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.
Is this designed behaviour of Swift?
I think this is a compiler bug. If you make a LetReq
an optional string, it works as expected:
struct LetReq: Req {
let path: String? = "LetReq"
}
File a bug with Apple.
I think that behavior is correct.
struct LetReq: Req {
let path = "LetReq"
}
path is String
type not String?
var req: Req!
req = LetReq()
req.path
req
is type of Req
. So req.path
means type is String?
and name is path
Req
's extension has default variable for path
variable. so req.path
refer that variable not LetReq
's path
It's vague... But I would bet on a bug.
At least for current implementation( swiftc
2.2);
This can be proven by this.
struct AA {
func a() -> String { return "" }
func a() -> String? { return "" }
var b: String { return "" }
var b: String? { return "" } // Error: Invalid redeclaraion of `b`.
}
But anyway, the compiler doesn't seem to check this redeclaration by protocol extension. So, LetReq
instance actually provides two properties.
var path: String { get }
var path: String? { get }
You can check this with this.
print(LetReq().path as String?) // prints `Optional("Req")`.
print(LetReq().path as String) // prints `LetReq`.
I believe this kind of property overloading must be prevented by compiler. For same reason of why they prevented property overloading in struct AA
. So, that's a bug in my opinion.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.