为什么可变类型不是不可变类型的子类型?
Why isn't mutable a subtype of immutable, or vice versa?
在编程语言的类型系统中,可变(mutable)与不可变(immutable)数据结构为何不能互为子类型?这并非技术限制,而是为了严格遵守Liskov substitution principle。如果将可变类型视为不可变类型的子类型,当代码期望不可变对象时传入可变对象,后续对对象的修改会破坏原有的不变性契约,导致哈希值失效等严重问题。文章通过pair数据结构的例子,深入剖析了类型安全背后的逻辑,并探讨了如何通过type classes或duck typing等机制,在不牺牲类型安全的前提下实现灵活的多态调用。
我记得当我第一次了解到不可变性的那一刻,它改变了一切。
HN 评论区
11- BlackFly
如果你将可变性与独占访问权配对,那么你就解决了这里由(有些人可能会说是过于)严格的子类型定义所提出的异议,同时也解决了试图就这一异议进行争论的问题。任何请求不可变实例的代码永远都不会观察到可变性,因为对不可变引用的请求是独占的。因此,你可以传递可变引用,但只要某个东西持有该引用,其他代码就无法再访问其可变性。
所以,可变性异或别名化提供了这种严格的子类型关系。当然,你还需要通过提供没有此类契约的对象来放松这种限制,这时你就进入了内部可变性的领域。在那里,可变方法同样可以被理解为子类型的一部分,因为明确被告知没有保证对象不会发生变化的引用持有者,本身就接受了这一点。
- raincole
换句话说,不可变不等于只读。
在 C# 中,ReadOnlyCollection<T> 和 ImmutableArray<T> 正是出于这个原因而完全是两码事。
- comrade1234
在几种语言中,NSMutableArray 不是 NSArray 的子类吗?