不变性和可变性基础

可变性与不可变性

在哲学中,有一个被称为“忒修斯之船(Ship of Theseus)”的思想实验。这是西方哲学中最古老的概念之一,大致如下:

英雄忒修斯的著名船只被保存在港口作为博物馆展品。随着岁月流逝,木质部件逐渐腐烂并被替换。一百年后,这艘船的所有木质部件都已被替换。问题是:它还是同一艘船吗?

对于这个问题,有很多种回答方式,可以在维基百科上查到。我们感兴趣的是,这个关于身份的问题同样可以应用到编程中。在编程里,一个与变化和身份直接相关的重要概念就是 (不)可变性(mutability/immutability)


可变性字面意思是“可被改变的性质”,在编程中,它指的是对象在被创建之后,其状态是否可以改变。

沿着这条思路,我们可以区分可变对象不可变对象。简单来说:

  • 可变对象在创建后可以被修改。

  • 不可变对象在创建后不能被修改。

这是可变对象和不可变对象的关键区别。

这在实践中意味着什么?
不可变对象总是代表同一个值:如果你想要一个不同的值,你必须创建一个全新的对象。
而可变对象则更方便,我们可以在不创建新对象的情况下直接修改它们的值。

回到忒修斯之船,如果我们把它看作一个不可变对象,那么答案是:一旦改变了什么,就已经是一个不同的对象。换句话说,即使它还叫“忒修斯之船”,它也不再是原本的那艘船。

相反,如果我们把它看作一个可变对象,那么答案是:它还是同一艘船”。因为这些改变并没有影响它的身份。

在不同的编程语言中,不同类型的对象可能是不可变的。
例如:

  • PythonJava 中,字符串是不可变的。

  • 但在 Java 中,还有 StringBuilderStringBuffer,它们是可变的。

  • RubyPHP 中,字符串是可变的。

因此,当你在你最喜欢的编程语言中编写程序时,你需要注意哪些对象是可变的,哪些是不可变的。


自定义对象与不可变性

一般来说,自定义类的对象是可变的。
但是,在某些情况下我们希望它们是不可变的:不可变对象是线程安全的,更容易测试,也可能更安全。

  • 不可变对象可以在不同线程之间安全共享,而无需额外的保护措施。

  • 可变对象的状态很难追踪,因为它们随时可能被任何工作线程修改。

在自定义对象的语境中,我们还可以谈到弱不可变性(weak immutability)强不可变性(strong immutability)

  • 弱不可变性:对象的一部分字段是不可变的,另一部分是可变的。

  • 强不可变性:对象的所有字段都是不可变的。

具体如何让一个自定义类不可变依赖于语言本身,但有一些通用的指导原则:

  • 禁止在对象创建后修改字段值,或者禁止字段被重新赋值。

  • 可以通过将字段设置为只读或常量来实现。

  • 也可以修改设置属性值的方法,让它们在调用时抛出异常。

  • 还可以使用访问修饰符:让字段在类外部无法访问。


总结

总而言之,可变对象和不可变对象的区别在于:

  • 可变对象:创建后可以修改其状态。

  • 不可变对象:创建后不能修改其状态。

不同编程语言有自己的可变/不可变对象划分。
自定义类通常是可变的,但在需要时,可以使用语言特定的工具和技术让它们变成不可变对象。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值