![](/img/trans.png)
[英]Swift: Store Type of implementation of Protocol in static var of protocol extension
[英]Swift protocol extension `var { get }` override implementation's `let`
当将实现结构分配给类型为protocol
的变量时,使用var
和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 的设计行为吗?
我认为这是一个编译器错误。 如果您将LetReq
可选字符串,它会按预期工作:
struct LetReq: Req {
let path: String? = "LetReq"
}
向 Apple提交错误。
我认为这种行为是正确的。
struct LetReq: Req {
let path = "LetReq"
}
路径是String
类型不是String?
var req: Req!
req = LetReq()
req.path
req
是Req
类型。 所以req.path
表示类型是String?
名称是path
Req
的扩展具有path
变量的默认变量。 所以req.path
指的是变量不是LetReq
的path
这很模糊......但我敢打赌一个错误。
至少对于当前的实现( swiftc
2.2);
这可以证明这一点。
struct AA {
func a() -> String { return "" }
func a() -> String? { return "" }
var b: String { return "" }
var b: String? { return "" } // Error: Invalid redeclaraion of `b`.
}
但无论如何,编译器似乎并没有通过协议扩展来检查这个重新声明。 所以, LetReq
实例实际上提供了两个属性。
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
属性重载。 所以,在我看来,这是一个错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.