我知道这已经讨论过很多次了,但我不确定我是否真的理解为什么Java 和 C# 设计者选择从这些语言中省略这个特性。我对如何解决问题(使用接口、克隆或任何其他替代方法)不感兴趣,而是对决定背后的基本原理感兴趣。
从语言设计的角度来看,为什么这个功能被拒绝了?
PS:我使用了诸如“省略”之类的词,有些人可能会觉得这不够用,因为 C# 是按照加法(而不是减法)方法设计的。但是,我之所以使用这些词,是因为该功能在设计这些语言之前就存在于 C++ 中,因此在从程序员的工具箱中删除的意义上省略了它。
我知道这已经讨论过很多次了,但我不确定我是否真的理解为什么Java 和 C# 设计者选择从这些语言中省略这个特性。我对如何解决问题(使用接口、克隆或任何其他替代方法)不感兴趣,而是对决定背后的基本原理感兴趣。
从语言设计的角度来看,为什么这个功能被拒绝了?
PS:我使用了诸如“省略”之类的词,有些人可能会觉得这不够用,因为 C# 是按照加法(而不是减法)方法设计的。但是,我之所以使用这些词,是因为该功能在设计这些语言之前就存在于 C++ 中,因此在从程序员的工具箱中删除的意义上省略了它。
在这次采访中,安德斯说:
安德斯·海尔斯伯格:是的。关于 const,这很有趣,因为我们也经常听到这样的抱怨:“你为什么没有 const?” 问题中隐含的是,“为什么你没有运行时强制执行的 const ?” 这确实是人们在问的问题,尽管他们不会这样说。
const 在 C++ 中起作用的原因是你可以抛弃它。如果你不能把它扔掉,那么你的世界就会糟透了。如果你声明一个接受 const Bla 的方法,你可以传递一个非常量 Bla。但是如果反过来就不行了。如果您声明一个采用非常量 Bla 的方法,则不能将其传递给 const Bla。所以现在你被卡住了。所以你逐渐需要一个非 const 的东西的 const 版本,你最终会得到一个影子世界。在 C++ 中你可以摆脱它,因为与 C++ 中的任何东西一样,无论你是否想要这个检查都是完全可选的。如果你不喜欢它,你可以把它打掉。
我想主要是因为:
两者都可能有问题。但尤其是第一个:如果不能保证,那有什么用?更好的选择可能是:
至于他们为什么这样做,相关人士是这么说的:
http://blogs.msdn.com/ericgu/archive/2004/04/22/118238.aspx http://blogs.msdn.com/slippman/archive/2004/01/22/61712.aspx Raymond 也提到陈 http://blogs.msdn.com/oldnewthing/archive/2004/04/27/121049.aspx
在多语言系统中,这将非常复杂。
至于Java,您将如何拥有这样的属性?已经有使对象不可变的技术,这可以说是实现这一目标的更好方法,并具有额外的好处。事实上,你可以通过声明一个只实现不改变状态的方法的超类/超接口,然后拥有一个实现变异方法的子类/子接口来模拟 const 行为。通过将可变类向上转换为没有写入方法的类实例,其他代码位无法修改对象,除非专门将其转换回可变版本(相当于丢弃const
)。
即使您不希望对象是严格不可变的,如果您真的想要(我不推荐),您也可以在其上设置某种“锁定”模式,以便它只能在解锁时发生变异。让锁定/解锁方法是私有的,或者适当地受到保护,并且您可以在那里获得某种程度的访问控制。或者,如果您根本不打算使用将其作为参数的方法来修改它,请传入该对象的副本,或者如果复制整个对象过于繁重,那么其他一些仅包含必要的轻量级数据对象信息。您甚至可以使用动态代理来为您的对象创建一个代理,它将对突变方法的任何调用转换为无操作。
基本上已经有很多方法可以防止类被变异,这让您可以选择最适合您的情况的方法(提示:尽可能选择纯不变性,因为它使对象变得简单线程安全并且通常更容易推理)。对于如何const
实现这些技术没有明显的语义,这将是对这些技术的改进,这将是另一回事,要么缺乏灵活性,要么灵活到无用。
也就是说,除非我错过了什么,这是完全可能的。:-)
Java 有自己的 const 版本;最终的。Joshua Bloch 在其Effective Java中描述了 如何有效地使用 final 关键字。(顺便说一句,const 是 Java 中的保留关键字,以备将来出现差异)