复用对象创建新对象以使用点符号特性是否为良好实践?
通过复用对象属性创建新对象是否属于良好实践?
嗨,这个问题问得特别接地气!其实这种基于已有对象复用通用属性、仅修改差异属性来创建新对象的做法,在绝大多数场景下都是非常实用的良好实践,但得结合语言特性和具体场景来灵活处理,避免踩坑。
先看看你给出的代码例子:三个Tip实例里,body、sourceName、sourceURL这些属性完全重复,每次都从头写一遍不仅冗余,后期维护也头疼——哪天sourceName要改,你得挨个修改三个实例,很容易漏改出错。
为什么这种复用方式是好实践?
- 减少重复代码:把通用属性抽成基础模板,只关注差异部分,代码可读性瞬间提升
- 降低维护成本:通用属性只需要在模板里改一次,所有基于模板创建的对象都会同步受益
- 逻辑更清晰:用点符号修改特定属性,一眼就能看出新对象和模板的差异点
具体怎么实现更优雅?
情况1:如果Tip是值类型(比如Swift结构体)
值类型赋值时会自动拷贝整个对象,修改新对象不会影响原模板,直接复用就很安全:
// 先定义一个包含通用属性的基础模板 let baseGymTip = Tip( title: "", body: "body text, yada, yada, yada.", sourceName: "SourceName", sourceURL: "www.test.com", sponsorLogo: "TBD", sponsorURL: "www.test.com" ) // 基于模板创建新对象,仅修改差异属性 var tipAM1 = baseGymTip tipAM1.title = "Gym 1 Title" var tipAM2 = baseGymTip tipAM2.title = "Gym 2 Title" var tipAM3 = baseGymTip tipAM3.title = "Gym 3 Title"
情况2:如果Tip是引用类型(比如Swift类)
直接赋值会让多个变量指向同一个内存对象,修改新对象会意外改变原模板和其他实例的属性,这时候建议给类封装一个「拷贝并修改」的方法:
class Tip { let title: String let body: String let sourceName: String let sourceURL: String let sponsorLogo: String let sponsorURL: String init(title: String, body: String, sourceName: String, sourceURL: String, sponsorLogo: String, sponsorURL: String) { self.title = title self.body = body self.sourceName = sourceName self.sourceURL = sourceURL self.sponsorLogo = sponsorLogo self.sponsorURL = sponsorURL } // 封装一个方法,基于当前对象创建新实例,允许修改指定属性 func with(title: String? = nil, body: String? = nil) -> Tip { return Tip( title: title ?? self.title, body: body ?? self.body, sourceName: self.sourceName, sourceURL: self.sourceURL, sponsorLogo: self.sponsorLogo, sponsorURL: self.sponsorURL ) } } // 使用方式简洁又安全: let baseGymTip = Tip( title: "", body: "body text, yada, yada, yada.", sourceName: "SourceName", sourceURL: "www.test.com", sponsorLogo: "TBD", sponsorURL: "www.test.com" ) let tipAM1 = baseGymTip.with(title: "Gym 1 Title") let tipAM2 = baseGymTip.with(title: "Gym 2 Title") let tipAM3 = baseGymTip.with(title: "Gym 3 Title")
什么时候需要谨慎使用?
- 如果每个新对象的属性差异很大,复用模板反而会让代码逻辑变模糊,不如直接创建新实例
- 对于完全不可变的对象(比如所有属性都是
let的类),直接修改属性是不允许的,必须用「拷贝并修改」的方式
内容的提问来源于stack exchange,提问作者ajenson
相关产品推荐
相关产品推荐

