operator 為什麼Java不提供運算符重載?



operator overwrite c++ (12)

從C ++到Java,一個明顯的未解決的問題是為什麼Java沒有包含運算符重載?

不是Complex a, b, c; a = b + c; Complex a, b, c; a = b + c;Complex a, b, c; a = b.add(c);簡單得多Complex a, b, c; a = b.add(c); Complex a, b, c; a = b.add(c);

是否有一個已知的原因,這是有效的論點,不允許運算符重載? 原因是任意的,還是失去時間?


Answer #1

假設你想覆蓋a引用的對象的前一個值,那麼必須調用一個成員函數。

Complex a, b, c;
// ...
a = b.add(c);

在C ++中,此表達式告訴編譯器在堆棧上創建三(3)個對象,執行加法,並將臨時對象的結果值複製到現有對象a

但是,在Java中, operator=不會為引用類型執行值複製,並且用戶只能創建新的引用類型,而不能創建值類型。 因此,對於名為Complex的用戶定義類型,賦值意味著將引用複製到現有值。

相反,請考慮:

b.set(1, 0); // initialize to real number '1'
a = b; 
b.set(2, 0);
assert( !a.equals(b) );

在C ++中,這會復制該值,所以比較結果不會相等。 在Java中, operator=執行引用複制,所以ab現在引用相同的值。 因此,比較會產生“相等”,因為對象將與自身相等。

副本和引用之間的差異只會增加運算符重載的混淆。 正如@Sebastian所說,Java和C#都必須分別處理值和引用的相等性 - operator+可能會處理值和對象,但operator=已經實現來處理引用。

在C ++中,你只應該一次處理一種比較,所以它可能不那麼令人困惑。 例如,在Complexoperator=operator==都處理值 - 分別複製值和比較值。


Answer #2

從技術上講,每種編程語言都有操作符重載,可以處理不同類型的數字,例如整數和實數。 說明:術語超載意味著一個函數只有幾個實現。 在大多數編程語言中,為運算符+提供了不同的實現,一個用於整數,一個用於實數,這稱為運算符重載。

現在,很多人發現Java有操作符重載操作符+以將字符串添加到一起,並且從數學的角度來看,這確實很奇怪,但是從編程語言的開發者的角度來看,添加內置操作符重載沒有任何問題對於運營商+其他類如String。 然而,大多數人都同意,一旦為String增加了內置重載+,那麼為開發人員提供這個功能通常也是一個好主意。

完全不同意運算符重載混淆代碼的謬誤,因為這是由開發人員決定的。 這是天真的想法,而且很老實,它變老了。

用於在Java 8中添加運算符重載的+1。


Answer #3

This is not a good reason to disallow it but a practical one:

People do not always use it responsibly. Look at this example from the Python library scapy:

>>> IP()
<IP |>
>>> IP()/TCP()
<IP frag=0 proto=TCP |<TCP |>>
>>> Ether()/IP()/TCP()
<Ether type=0x800 |<IP frag=0 proto=TCP |<TCP |>>>
>>> IP()/TCP()/"GET / HTTP/1.0\r\n\r\n"
<IP frag=0 proto=TCP |<TCP |<Raw load='GET / HTTP/1.0\r\n\r\n' |>>>
>>> Ether()/IP()/IP()/UDP()
<Ether type=0x800 |<IP frag=0 proto=IP |<IP frag=0 proto=UDP |<UDP |>>>>
>>> IP(proto=55)/TCP()
<IP frag=0 proto=55 |<TCP |>>

Here is the explanation:

The / operator has been used as a composition operator between two layers. When doing so, the lower layer can have one or more of its defaults fields overloaded according to the upper layer. (You still can give the value you want). A string can be used as a raw layer.


Answer #4

那麼你真的可以在操作員超載的情況下在自己的腳下開槍自殺。 就像人們用指針一樣,他們犯了愚蠢的錯誤,所以決定拿走剪刀。

至少我認為這是原因。 無論如何,我在你身邊。 :)


Answer #5

James Gosling將Java設計為以下內容:

“當你從一間公寓搬到另一間公寓時,有一個關於搬家的原則,一個有趣的實驗是收拾你的公寓,把所有東西都放進箱子裡,然後搬進下一間公寓,在你需要的時候不要打開任何東西,重新做你的第一頓飯,然後你從盒子裡拿出東西,然後在一個月左右的時間裡,你已經用它來很清楚你生活中真正需要什麼東西,然後把剩下的東西 - 忘記你有多喜歡它,或者它有多酷 - 然後你就把它扔掉了,這簡直令人驚訝,它簡化了你的生活,你可以在各種設計問題中使用這個原則:不要僅僅因為它們很酷,或者只是因為它們很有趣。“

你可以http://www.gotw.ca/publications/c_family_interview.htm閱讀http://www.gotw.ca/publications/c_family_interview.htmhttp://www.gotw.ca/publications/c_family_interview.htm

基本上,運算符重載對模擬某種點,貨幣或複數的類非常有用。 但在此之後,您將很快開始耗盡示例。

另一個因素是開發人員濫用C ++中的功能,如'&&','||',演員操作員和當然'新'等。 Exceptional C ++書中詳細介紹了將此與傳值和異常相結合導致的複雜性。


Answer #6

我認為這可能是一個有意識的設計選擇,迫使開發人員創建名稱明確表達意圖的函數。 在C ++中,開發人員會重載運算符,而這些運算符通常與給定運算符的普遍接受性無關,因此幾乎不可能在沒有查看運算符的定義的情況下確定一段代碼的作用。


Answer #7

查看Boost.Units: 鏈接文本

它通過運算符重載提供零開銷維度分析。 這可以清楚多少?

quantity<force>     F = 2.0*newton;
quantity<length>    dx = 2.0*meter;
quantity<energy>    E = F * dx;
std::cout << "Energy = " << E << endl;

實際上會輸出“Energy = 4 J”,這是正確的。


Answer #8

有人說Java中的運算符重載會導致混淆。 那些人有沒有停下來看看一些Java代碼做一些基本的數學運算,比如使用BigDecimal以百分比增加財務價值? ......這樣一種練習的冗長變成了自己對混淆的表現。 Ironically, adding operator overloading to Java would allow us to create our own Currency class which would make such mathematical code elegant and simple (less obsfuscated).


Answer #9

Sometimes it would be nice to have operator overloading, friend classes and multiple inheritance.

However I still think it was a good decision. If Java would have had operator overloading then we could never be sure of operator meanings without looking through source code. At present that's not necessary. And I think your example of using methods instead of operator overloading is also quite readable. If you want to make things more clear you could always add a comment above hairy statements.

// a = b + c
Complex a, b, c; a = b.add(c);

Answer #10

說操作符重載會導致邏輯錯誤,該操作符與操作邏輯不匹配,這就像什麼都沒說。 如果函數名不適合操作邏輯,那麼會出現相同類型的錯誤 - 那麼解決方案是什麼:降低函數使用的能力!? 這是一個滑稽的回答 - “不適合操作邏輯”,每個參數名稱,每個類別,函數或任何可能在邏輯上都不合適的答案。 我認為這個選項應該以可敬的編程語言提供,那些認為它是不安全的 - 嘿,沒有兩個人說你必須使用它。 讓我們拿C#。 他們貶低了指針,但嘿 - 有'不安全的代碼'聲明 - 根據您自己的風險進行編程。


Answer #11

Groovy有運算符重載,並在JVM中運行。 如果你不介意性能受到影響(每天都會變小)。 它是基於方法名稱的自動化。 例如,'+'調用'加(參數)'方法。


Answer #12

Java設計人員認為運算符超載比其值得的更麻煩。 就那麼簡單。

在一種語言中,每一個對像變量實際上都是一個引用,但是對於一個C ++程序員來說,操作符重載會帶來更多的不合邏輯的危險。 將情況與C#的==運算符重載以及Object.EqualsObject.ReferenceEquals (或任何它所稱的)進行比較。





operator-overloading