Swift 协议默认值不可更改
我有这样一个带有默认值的协议属性。但在当前的实现中,如果我使用 avgPrice
、precision
的一些其他值创建 AssetViewAttributes
实例,它们仍然具有默认值。我怎样才能改变它们?
struct Crypto: AssetViewAttribures {
let name: String
let logo: URL
let symbol: String
let avgPrice: String
let precision: Int
}
struct Commodity: AssetViewAttribures {
let name: String
let logo: URL
let symbol: String
let avgPrice: String
let precision: Int
}
struct Fiat: AssetViewAttribures {
let name: String
let logo: URL
let symbol: String
}
protocol AssetViewAttribures {
var name: String { get }
var logo: URL { get }
var symbol: String { get }
}
extension AssetViewAttribures {
var avgPrice: String { get { return "" } set {} }
var precision: Int { get{ return 0 } set{} }
}
var type1: AssetViewAttribures = Crypto(name: "name", logo: URL(string: "https://pixabay.com/de/illustrations/online-maus-web-internet-weltweit-523234/")!, symbol: "symbol", avgPrice: "123", precision: 2)
type1.avgPrice // "" instead of "123"
I have such a protocol properties with default values. But with the current implementation if I create an instance of AssetViewAttributes
with some other values for avgPrice
, precision
they still have the default values. How can I change them?
struct Crypto: AssetViewAttribures {
let name: String
let logo: URL
let symbol: String
let avgPrice: String
let precision: Int
}
struct Commodity: AssetViewAttribures {
let name: String
let logo: URL
let symbol: String
let avgPrice: String
let precision: Int
}
struct Fiat: AssetViewAttribures {
let name: String
let logo: URL
let symbol: String
}
protocol AssetViewAttribures {
var name: String { get }
var logo: URL { get }
var symbol: String { get }
}
extension AssetViewAttribures {
var avgPrice: String { get { return "" } set {} }
var precision: Int { get{ return 0 } set{} }
}
var type1: AssetViewAttribures = Crypto(name: "name", logo: URL(string: "https://pixabay.com/de/illustrations/online-maus-web-internet-weltweit-523234/")!, symbol: "symbol", avgPrice: "123", precision: 2)
type1.avgPrice // "" instead of "123"
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这将调用协议扩展中声明的 getter,它只返回
""
。这是因为Crypto.avgPrice
与协议扩展中声明的avgPrice
没有关系。您无法“覆盖”扩展中的成员,因为扩展是静态调度的。编译器发现test
的类型为AssetViewAttributes
,找到您在扩展中声明的默认 getter,这就是它将调用的内容。要解决此问题,您需要添加
avgPrice
作为协议的要求:这会导致 Swift 查找协议中声明的
avgPrice
,并动态地调度它。如果实现类碰巧实现了avgPrice,则将调用该实现。如果没有,则调用默认实现。This would call the getter declared in the protocol extension, which just returns
""
. This is becauseCrypto.avgPrice
has no relation to theavgPrice
declared in the protocol extension. You can't "override" a member in an extension, because extensions are dispatched statically. The compiler sees thattest
is of typeAssetViewAttributes
, finds the default getter you have declared in the extension, and that's what it will call.To fix this, you need to add
avgPrice
as a requirement of the protocol:This causes Swift to find
avgPrice
declared in the protocol, and dispatches it dynamically. If the implementing class happens to implementavgPrice
, that implementation will be called. If not, then the default implementation is called.