ska*_*man 153 c++ scala operator-overloading
C++中的运算符重载被许多人认为是坏事(tm),并且在新语言中不会重复错误.当然,这是设计Java时专门删除的一个功能.
现在我开始阅读Scala,我发现它看起来非常像运算符重载(虽然从技术上来说它没有运算符重载,因为它没有运算符,只有函数).但是,它似乎与C++中的运算符重载没有本质上的区别,因为我记得运算符被定义为特殊函数.
所以我的问题是什么使得在Scala中定义"+"的想法比在C++中更好?
Jam*_*Iry 239
C++从C继承了真正的蓝色运算符.我的意思是6 + 4中的"+"非常特殊.例如,您不能获得指向该+函数的指针.
另一方面,Scala没有这样的运算符.它在定义方法名称和非字符号的一些内置优先级方面具有很大的灵活性.所以从技术上讲,Scala没有运算符重载.
无论你想要什么,运算符重载本身并不坏,即使在C++中也是如此.问题在于糟糕的程序员滥用它.但坦率地说,我认为剥夺程序员滥用运算符重载的能力并不能解决程序员可能滥用的所有问题.真正的答案是指导. http://james-iry.blogspot.com/2009/03/operator-overloading-ad-absurdum.html
尽管如此,C++的运算符重载和Scala的灵活方法命名之间存在差异,恕我直言,这使得Scala不那么容易滥用和更容易被滥用.
在C++中,获取in-fix表示法的唯一方法是使用运算符.否则,您必须使用object.message(参数)或指针 - > messsage(参数)或函数(argument1,argument2).因此,如果您希望代码具有某种DSLish风格,那么使用运算符会有压力.
在Scala中,您可以通过任何消息发送获取中缀表示法."对象消息参数"完全没问题,这意味着您不需要使用非单词符号来获取中缀表示法.
C++运算符重载仅限于C运算符.结合只有操作符可以使用的限制,这会给人们施加压力,试图将各种不相关的概念映射到相对较少的符号,如"+"和">>"
Scala允许使用大量有效的非单词符号作为方法名称.例如,我有一个嵌入式Prolog-ish DSL,你可以写
female('jane)! // jane is female
parent('jane,'john)! // jane is john's parent
parent('jane, 'wendy)! // jane is wendy's parent
mother('Mother, 'Child) :- parent('Mother, 'Child) & female('Mother) //'// a mother of a child is the child's parent and is female
mother('X, 'john)? // find john's mother
mother('jane, 'X)? // find's all of jane's children
Run Code Online (Sandbox Code Playgroud)
: - ,!,?和&符号被定义为普通方法.仅在C++中并且有效,因此尝试将此DSL映射到C++将需要一些已经引起非常不同的概念的符号.
当然,这也使Scala遭受了另一种虐待.在Scala中,如果需要,可以将方法命名为$!&^%.
对于像Scala一样灵活使用非单词函数和方法名称的其他语言,请参阅Smalltalk,其中,像Scala一样,每个"运算符"只是另一种方法,Haskell允许程序员定义灵活命名的优先级和固定性功能.
小智 66
许多人认为C++中的运算符重载是坏事(tm)
只有无知.在像C++这样的语言中绝对需要它,并且值得注意的是,其他开始采用"纯粹主义"观点的语言,一旦他们的设计师发现它有多么必要,就添加了它.
Fai*_*ali 41
在C++中,运算符重载从未被普遍认为是一个坏主意 - 只是滥用运算符重载被认为是一个坏主意.一个人不需要语言中的运算符重载,因为无论如何它们都可以使用更详细的函数调用进行模拟.避免Java中的运算符重载使得Java的实现和规范变得更加简单,并且它迫使程序员不要滥用运算符.Java社区中有一些关于引入运算符重载的争论.
Scala中运算符重载的优点和缺点与C++中的相同 - 如果适当地使用运算符重载,则可以编写更自然的代码 - 如果不这样,可以使用更加神秘,混淆的代码.
FYI:运营商不是在C++定义为特殊功能,它们的行为就像任何其他的功能 - 虽然在名称查找一些差异,是否他们需要的是成员函数,而事实上,他们可以通过两种方式调用:1 )运算符语法,以及2)operator-function-id语法.
jma*_*g2k 18
本文 - " C++和Java的积极遗产 " - 直接回答您的问题.
"C++既有堆栈分配又有堆分配,你必须重载你的操作符来处理所有情况而不会导致内存泄漏.确实很困难.但是,Java有一个存储分配机制和一个垃圾收集器,这使得运营商重载变得微不足道". ..
Java错误地(根据作者)省略了运算符重载,因为它在C++中很复杂,但是忘了为什么(或者没有意识到它不适用于Java).
值得庆幸的是,像Scala这样的高级语言为开发人员提供了选项,同时仍然在同一个JVM上运行.
运算符重载没有错.事实上,还有一些错误不具有运算符重载数字类型.(看一下使用BigInteger和BigDecimal的一些Java代码.)
但是,C++具有滥用该功能的传统.一个经常被引用的例子是比特移位运算符过载以进行I/O.
一般来说,这不是一件坏事.
C#等新语言也有运算符重载.
滥用运算符重载是一件坏事.
但是C++中定义的运算符重载也存在问题.因为重载运算符只是方法调用的语法糖,所以它们的行为就像方法一样.另一方面,普通的内置运算符的行为与方法不同.这些不一致可能会导致问题.
我的头顶操作员||和&&.
这些内置版本是快捷操作符.对于重载版本而言,情况并非如此,并且已导致一些问题.
事实上+ - */all返回它们运行的相同类型(在运算符提升之后)
重载版本可以返回任何内容(这是滥用设置的位置,如果您的运算符开始返回某些仲裁器类型,则用户不期望事情走下山).
小智 7
操作符重载不是你真正"经常"需要的东西,但是当你使用Java时,如果你真的需要它,它会让你想要撕掉你的指甲,这样你就有借口停止打字.
你刚刚发现的代码溢出了很长时间?是的,你将不得不重新输入整个批次以使其适用于BigInteger.没有什么比仅仅为了改变变量的类型而重新发明轮子更令人沮丧的了.
Guy Steele认为运营商超载也应该是Java,在他的主题演讲"发展一种语言" - 有一个视频和它的转录,这真是一个惊人的演讲.你会想知道他在前几页会谈到什么,但如果你继续阅读,你会看到重点并获得启示.事实上他可以做这样的演讲也很神奇.
与此同时,这次演讲激发了许多基础研究,可能包括Scala--这是每个人都应该阅读以在该领域工作的论文之一.
回到这一点,他的例子主要是关于数字类(比如BigInteger,以及一些更奇怪的东西),但这并不重要.
但是,错误地使用运算符重载可能会导致可怕的结果,如果您尝试读取代码而不仔细研究它使用的库,那么即使正确使用也会使问题复杂化.但这是个好主意吗?OTOH,这些图书馆是否应该尝试为其运营商提供操作员备忘单?