Swift中存储属性标记open与public的差异问询
Swift存储属性:open vs public 的真实差异
Great question—this is such a tricky gotcha in Swift’s access control, especially since stored properties behave way differently from computed ones when it comes to open vs public. Let’s break this down clearly:
核心结论:对于存储属性,open 和 public 没有功能差异
First off: 标记为open的存储属性和public的存储属性在行为上完全一致。Neither can be overridden by a stored property in a subclass—your example’s compile error isn’t because of the open keyword, it’s because Swift never lets you override a stored property with another stored property, no matter the access level.
理解open的真正作用
The open keyword in Swift has two key jobs:
- It marks a class as inheritable across module boundaries (a
publicclass can only be subclassed within its own module). - It marks class members (methods, computed properties, subscripts) as overridable across module boundaries (a
publicmember can only be overridden within its own module).
But stored properties don’t fit into the "overridable" category at all. Stored properties are just chunks of memory holding values—if Swift let you override one with another stored property, you’d end up with two separate values for the same name in the subclass instance, creating ambiguity and memory bloat. That’s why the compiler throws that error whenever you try to use override with a stored property, regardless of whether the parent property is open or public.
那open存储属性能做什么public做不到的?
Short answer: Nothing, when it comes to stored properties. Both access levels let you:
- Access the property from outside its module.
- Read/write it (if it’s a
var) from anywhere with access.
The only time open matters is if your class is open (so it can be subclassed across modules) and you have a computed property, method, or subscript marked open—those can be overridden in a subclass from another module. But for stored properties, the open tag is effectively redundant.
正确的“修改”存储属性行为的方式
If you want a subclass to adjust the behavior of a parent’s stored property, you can’t override it with another stored property. Instead, you have two valid options:
- Use a computed property in the subclass (works for both
openandpublicparent properties):open class God { open var hasSuperPowers = true } class HalfGod: God { override var hasSuperPowers: Bool { get { return false } set { // Sync with the parent's stored value if needed super.hasSuperPowers = newValue } } } - Turn the parent’s property into an
opencomputed property, so subclasses can override its get/set logic directly.
为什么Xcode不警告open存储属性是冗余的?
This is a fair frustration—Swift lets you apply open to stored properties even though it doesn’t change their behavior, which can definitely mislead developers into thinking they’re overridable. The likely reason is that Swift’s access control system prioritizes consistency: you can apply any access level keyword to any member, even if some combinations don’t add new functionality. It’s a tradeoff between system consistency and avoiding developer confusion.
内容的提问来源于stack exchange,提问作者J. Doe

