Java 运算符重载(Operator Overloading)原理

2020-12-04 13:40:25 +08:00
 Braisdom

Java 语言的出现是为了降低 C++ 的开发成本和学习难,但也将 C++ 一些非常有价值的特性搞丢了,运算符重载就是一个非常优秀的特性,但 Java 搞丢了,虽然运算符重载不是一个常用特性,但随着数据分析领域的发展,表达式的编译也就有了强烈的需求。

首先,我解释一下为什么需要运算符重载,Java 是一个严谨的逻辑性编程语句,有丰富的工程化集成能力,通常 Java 编译后的代码只是 JVM 中运行,但也会在其它的可执行单元中运行,常见的有:数据库(关系型、对象型、KV 型和预计算引擎等)、也可通过是一次远程服务调用。倘若这类可执行单元的协议中存在表达式(算术、比较和逻辑),这也就意味着在 Java 中需要通过字符串的形式表现这类表达式,此时就会出现下列的代码:

目标输出协议:

"(sum(order.no) + 100) > 1000 and order.id < 999"

构造协议的 Java 代码:

and(gt(plus(funCall("sum", "order.no"), 100)), lt(fieldCall("order", "id"), 999));

对比一下将计算表达式转换为 Java 中的方法调用,变得极难理解,但这种方式也是目前大都 ORM 框架所使用的方式,这样做的方式可以使得构造过程动态化,而不是简单的字符串拼接,当然其它内部原理还是字符串拼接。

在这样的使用场景下,如果 Java 的表达式支持重载则会变的非常简单,下面是 ObjectiveSQL 的代码:

Order.Table order = Order.asTable();

Expression expr = (sum(order.no) + 100) > 1000 && order.id < 999;

其中的Expression 是实现了 Java 运算符重载,内部有种数学计算、比较和逻辑计算的相关方法,最终也是通过拼接字符串的形式输出上述目标协议。

详细可参考: https://github.com/braisdom/ObjectiveSql

如果认可项目,请点个赞,欢迎交流...

4919 次点击
所在节点    程序员
48 条回复
Braisdom
2020-12-04 21:22:43 +08:00
@callofmx 如果语言可以选择,kotlin 不是我最佳选择。

算符重载 适合不同的场景,滥用了也就失去意义了
namelosw
2020-12-04 23:35:18 +08:00
@Braisdom 我已经说了, 问题是优先级. 所以:

1. 主要问题不在操作符重载, 而在于有优先级而不强制括号才会导致你的表达式看不清. LISP 可以乱用操作符, 也没看谁搞不清, 因为跟普通函数没有任何区别.
2. 次要问题是传递性, 即使是同一个操作符优先级一样, 也有左传递右传递问题, 比如加减和赋值的传递是相反的.

写一个 C 语言的 parser 你就全理解了.
Braisdom
2020-12-05 09:32:38 +08:00
@namelosw 你说的很对,优先级是主要问题,是从数学延续下来的,也是目前无法改变的事实,只能用其它的方法来解决,表达式的表现力 相比 函数嵌套的表达力 还是强很多的。

所以重载在这种场景下,是必须的
1490213
2020-12-05 12:12:21 +08:00
我不认为加入运算符重载能带来的好处有多少,但重载操作符极大的增加了阅读代码的心智负担。这种东西本质就是有了一种新的 DSL,导致不能通过现有认知的心理模型去理解,必须重新学习或者查询,看到熟悉的符号也不能断定其意义。
另外,有了重载运算符,下一步是不是就需要搞 haskell 的自定义结合律和优先级了?学术语言或者专业语言搞搞可以理解,但是普通人使用的语言我觉得应该简化复杂度和清晰规则,而不是相反。
ruyu
2020-12-05 13:21:01 +08:00
所以 scheme 多好, scheme 表示不知道你们在争论什么
Braisdom
2020-12-05 13:28:19 +08:00
@1490213 @ruyu 兄弟,我们先要忘记一切,从纯粹的数学出发

1 ) Java 和 SQL 都有运算符,这就表明运算符是表示复杂表达式的最佳方式,我做的只是让两者一致。
2 ) haskell 是一个调试抽象的语言,可能会符合一部分人群,世界万物没有实质的对与错,只是喜欢和不喜欢
3 ) ObjectiveSQL 不是一个能够满足所有人偏好的技术,我只是想满足更多的人
ruyu
2020-12-05 15:20:20 +08:00
我觉得楼主这个挺好的, 我就歪个楼, scheme 根本不用争论运算符应不应该重载的问题, 因为它根本没有运算符 (
Braisdom
2020-12-05 15:31:07 +08:00
@ruyu 诚心做事,也希望得到更多人认可,https://github.com/braisdom/ObjectiveSql 这是我的项目,感兴的点个赞

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/732083

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX