Java禁止运算符重载,但是来自C ++我没有看到任何理由。在运算符符号是任何其他符号的语言中,相同的规则适用于“+”和“加号”,并且没有问题。那有什么意义呢?
编辑:更具体一点,告诉我哪个缺点是重载“+”可能超载“等于”。
答案 0 :(得分:7)
与Java中的许多其他内容一样,这是一个限制,因为如果使用不当可能会造成混淆。 (同样,因为它很容易出错,所以禁止使用指针算法。)我是Java的忠实粉丝,但我一般认为它不应该被禁止,因为它可以误用。
例如,BigInteger会因重载+运算符而受益匪浅。
答案 1 :(得分:4)
好的,我会尝试这样做,假设GabrielŠčerbák这样做是出于更好的理由,而不是用语言辱骂。
对我来说问题是可管理的复杂性:我面前有多少代码需要解码而不是简单阅读?
在大多数传统语言中,在看到表达式a + b
后,我知道会发生什么。变量a
和b
将一起添加。我非常有信心,在幕后代码将是非常简洁,非常快速的本机机器代码,添加两个数字,无论数字是短整数还是双精度或两者的混合。 (在某些语言中,我可能还必须假设这些可能是串联的字符串,但这是一个完全不同的问题的咆哮 - 但如果你从正确的角度看它,那就是这种咆哮的味道。)
当我创建自己的用户定义类型时 - 比如无处不在的复杂类型(以及为什么Complex不是现代语言中的标准数据类型方式超出我的地狱,但是,再次,是一个不同问题的咆哮) - 如果我重载一个操作符(或者,相反,如果操作符为我超载 - 我正在使用一个库,比如说),没有密切关注代码我我不会知道我现在在对象上调用(可能是虚拟的)方法,而不是在幕后为我生成非常紧凑,简洁的代码。我不会知道隐藏的转换,隐藏的临时变量,......以及编写许多运算符的所有内容。为了找出我的代码中真正发生的事情,我必须非常密切地关注每一行并跟踪可能距离代码中当前位置三个屏幕的声明。要说这阻碍了我对在我眼前流动的代码的理解是轻描淡写的。重要的细节正在丢失,因为语法糖使东西味道太美味。
当我被迫在对象上使用显式方法(甚至是静态方法或适用的全局方法)时,这对我来说是一个信号,当我正在阅读时,它告诉我潜在的成本开销和瓶颈等等。我知道,甚至没有考虑一下,我正在处理一个方法,我已经调度开销,我可能有临时对象创建和删除开销等等。一切都是在我面前的我面前 - 或者至少有足够的指标在我面前,我知道要更加小心。
我并不反对运算符重载。有时它会使代码更清晰,确实如此,尤其是当您对许多令人困惑的表达式进行复杂的计算时。但是,我完全可以理解为什么有人可能不想把它放到他们的语言中。
还有一个原因是不要从语言设计者的角度来看操作符重载。运算符重载使得非常非常非常困难的语法。 C ++已经因为近似不可解析而臭名昭着,其中一些构造(如运算符重载)就是它的原因。从有人写这种语言的观点来看,我完全可以理解为什么运算符重载被认为是一个坏主意(或者一个好主意在实现中很糟糕)。
(当然,除了你已经拒绝的其他原因之外,这就是全部。我会在我的旧C ++时代提交我自己的operator-,()
重载,这真的很烦人。 )
答案 2 :(得分:1)
运算符重载本身没有问题,但它实际上是如何使用的。只要你重写操作符有意义,语言仍然有意义,但如果你给操作符赋予其他含义,它会使语言不一致。
(一个例子是左移(<<))和右移(>>)操作符在C ++中是如何重载的意思是“输入”和“输出”......)
因此,忽略运算符重载的原因可能是误操作的风险大于运算符重载的好处。
答案 3 :(得分:1)
我认为Java将从扩展其运算符以涵盖内置的Number对象类型中受益匪浅。早期(1.0之前)的Java版本据说拥有它(因为没有原语 - 一切都是对象),但当时的VM技术使其从性能视图中望而却步。
但是对于一般允许用户定义的运算符重载,它不符合Java语言的精神。主要的问题很简单,很难实现一个符合你对象类型的数学运算符的运算符,它将打开很多不良实现的大门,导致很多难以找到(因此很昂贵)错误。您可以查看一般Java代码中有多少糟糕的等于实现(如违反合同),问题只会从那里变得更糟。
当然,有些语言会优先考虑权力和语法美,而不是这些问题,以及对他们更多的权力。它不是Java。
编辑:自定义+
运算符与自定义==
实现(在equals(Object)
方法中用Java捕获)有何不同?事实并非如此。只是通过允许操作员重载,对六年级学生来说直观的事情变得不真实。 equals(Object)
实施的真实体验表明,如此复杂的合同在现实世界中难以实施。
进一步编辑:让我澄清以上内容,因为我在编辑时缩短了它并丢失了这一点。数学中的+
运算符具有某些属性,其中之一就是任何一方的数字出现在哪个顺序无关紧要 - 它具有相同的结果。因此,即使是最简单的+
执行添加到集合的情况:
Collection a = ...
Collection b = ...
a + b;
System.out.println(a);
System.out.println(b);
对+
的直观理解会导致期望a + b
或b + a
会产生相同的结果,但当然他们不会。开始混合两种对象类型,这些对象类型在其plus方法(比如Collection和String)中作为参数使用,并且事情变得更难以理解。
现在肯定有可能在对象上设计运算符,这些运算符得到了很好的理解,并且与没有它们相比,可以产生更好,更易读和更易理解的代码。但重点是,在本土企业API中,您最终会看到的是代码混淆。
答案 4 :(得分:1)
有一些问题:
但即使完全禁止,你也不能总是保护白痴。
答案 5 :(得分:0)
关键在于,无论何时你看到代码中使用了一个加号,你都知道它确实知道它的操作数的类型(你总是用Java做的,因为它是强有力的)键入)。