it-swarm-id.com

Mengapa Java tidak menawarkan kelebihan operator?

Datang dari C++ ke Java, pertanyaan yang belum terjawab jelas adalah mengapa Java tidak termasuk operator overloading?

Bukankah Complex a, b, c; a = b + c; jauh lebih sederhana dari Complex a, b, c; a = b.add(c);?

Apakah ada alasan yang diketahui untuk hal ini, argumen yang valid untuk tidak mengizinkan overloading operator? Apakah alasannya sewenang-wenang, atau hilang waktu?

375
rengolin

Dengan asumsi Anda ingin menimpa nilai sebelumnya dari objek yang dirujuk oleh a, maka fungsi anggota harus dipanggil.

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

Dalam C++, ekspresi ini memberitahu kompiler untuk membuat tiga (3) objek pada stack, melakukan penambahan, dan menyalin nilai yang dihasilkan dari objek sementara ke objek yang ada a.

Namun, di Java, operator= tidak melakukan penyalinan nilai untuk tipe referensi, dan pengguna hanya dapat membuat tipe referensi baru, bukan tipe nilai. Jadi untuk jenis yang ditentukan pengguna bernama Complex, penugasan berarti menyalin referensi ke nilai yang ada.

Pertimbangkan sebagai gantinya:

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

Dalam C++, ini menyalin nilainya, sehingga perbandingannya akan menghasilkan tidak sama. Di Jawa, operator= melakukan salinan referensi, jadi a dan b sekarang merujuk pada nilai yang sama. Akibatnya, perbandingan akan menghasilkan 'sama', karena objek akan dibandingkan dengan dirinya sendiri.

Perbedaan antara salinan dan referensi hanya menambah kebingungan kelebihan operator. Seperti yang disebutkan @Sebastian, Java dan C # keduanya harus berurusan dengan nilai dan persamaan referensi secara terpisah - operator+ kemungkinan akan berurusan dengan nilai dan objek, tetapi operator= sudah diterapkan untuk menangani referensi.

Di C++, Anda hanya harus berurusan dengan satu jenis perbandingan pada satu waktu, sehingga bisa kurang membingungkan. Misalnya, pada Complex, operator= dan operator== keduanya bekerja pada nilai - nilai penyalinan dan nilai masing-masing membandingkan.

17
Aaron

James Gosling disamakan merancang Java sebagai berikut:

"Ada prinsip tentang pindah, ketika kamu pindah dari satu apartemen ke apartemen lain. Percobaan yang menarik adalah mengemas apartemenmu dan memasukkan semuanya ke dalam kotak-kotak, lalu pindah ke apartemen berikutnya dan tidak membongkar apa pun sampai kamu membutuhkannya. sedang membuat makanan pertama Anda, dan Anda mengeluarkan sesuatu dari kotak. Kemudian setelah sebulan atau lebih Anda telah menggunakannya untuk mengetahui apa saja hal-hal dalam hidup Anda yang sebenarnya Anda butuhkan, dan kemudian Anda mengambil sisa dari hal-hal - lupakan betapa Anda menyukainya atau betapa kerennya itu - dan Anda hanya membuangnya Sungguh menakjubkan bagaimana hal itu menyederhanakan hidup Anda, dan Anda dapat menggunakan prinsip itu dalam semua jenis masalah desain: tidak melakukan sesuatu hanya karena mereka Keren atau hanya karena mereka menarik. "

Anda dapat membaca konteks kutipan di sini

Pada dasarnya kelebihan operator sangat bagus untuk kelas yang memodelkan semacam titik, mata uang, atau angka kompleks. Tetapi setelah itu Anda mulai kehabisan contoh dengan cepat.

Faktor lain adalah penyalahgunaan fitur dalam C++ oleh pengembang yang membebani operator seperti '&&', '||', operator pemeran, dan tentu saja 'baru'. Kompleksitas yang dihasilkan dari menggabungkan ini dengan nilai by pass dan pengecualian tercakup dengan baik di Buku C++ Luar Biasa.

39
Garth Gilmour

Lihat Peningkatan.Unit: teks tautan

Ini memberikan analisis Dimensi nol overhead melalui operator kelebihan beban. Seberapa jelas ini bisa didapat?

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

akan benar-benar menampilkan "Energi = 4 J" yang benar.

20
user15793

Perancang Java memutuskan bahwa overloading operator lebih merepotkan daripada nilainya. Sederhana seperti itu.

Dalam bahasa di mana setiap variabel objek sebenarnya referensi, operator overloading mendapat bahaya tambahan menjadi sangat tidak logis - setidaknya untuk programmer C++. Bandingkan situasi dengan operator C # == yang kelebihan beban dan Object.Equals dan Object.ReferenceEquals (atau apa pun namanya).

11
Sebastian Redl

Groovy memiliki operator kelebihan, dan berjalan di JVM. Jika Anda tidak keberatan hit performa (yang semakin kecil setiap hari). Ini otomatis berdasarkan nama metode. mis., '+' memanggil metode 'plus (argumen)'.

8
noah

Saya pikir ini mungkin merupakan pilihan desain sadar untuk memaksa pengembang untuk membuat fungsi yang namanya dengan jelas mengomunikasikan niat mereka. Dalam C++ pengembang akan membebani operator dengan fungsionalitas yang sering kali tidak memiliki hubungan dengan sifat yang diterima secara umum dari operator yang diberikan, sehingga hampir tidak mungkin untuk menentukan apa yang dilakukan sepotong kode tanpa melihat definisi operator.

6
user14128

Nah, Anda dapat benar-benar menembak diri sendiri dengan operator yang kelebihan beban. Ini seperti dengan pointer orang membuat kesalahan bodoh dengan mereka dan jadi diputuskan untuk mengambil gunting.

Setidaknya kupikir itulah alasannya ... Aku tetap di sisimu. :)

5
Sarien

Secara teknis, ada kelebihan operator di setiap bahasa pemrograman yang dapat menangani berbagai jenis angka, mis. bilangan bulat dan bilangan real. Penjelasan: Istilah overloading berarti hanya ada beberapa implementasi untuk satu fungsi. Dalam sebagian besar bahasa pemrograman, implementasi yang berbeda disediakan untuk operator +, satu untuk bilangan bulat, satu untuk real, ini disebut operator overloading.

Sekarang, banyak orang merasa aneh bahwa Java memiliki operator kelebihan untuk operator + untuk menambahkan string bersama-sama, dan dari sudut pandang matematika ini memang aneh, tetapi dilihat dari sudut pandang pengembang bahasa pemrograman, tidak ada yang salah dengan menambahkan kelebihan operator bawaan untuk operator + untuk kelas lain mis Tali. Namun, sebagian besar orang setuju bahwa sekali Anda menambahkan kelebihan muatan bawaan untuk + untuk String, maka umumnya merupakan ide bagus untuk menyediakan fungsionalitas ini untuk pengembang juga.

Sepenuhnya tidak setuju dengan kekeliruan yang berlebihan dari operator mengaburkan kode, karena hal ini diserahkan kepada pengembang untuk memutuskan. Ini naif untuk berpikir, dan sejujurnya, sudah semakin tua.

+1 untuk menambahkan overloading operator di Java 8.

4
Olai

Mengatakan bahwa operator kelebihan muatan mengarah ke kesalahan logis tipe yang operator tidak cocok dengan logika operasi, itu seperti mengatakan apa-apa. Jenis kesalahan yang sama akan terjadi jika nama fungsi tidak sesuai untuk logika operasi - jadi apa solusinya: jatuhkan kemampuan penggunaan fungsi !? Ini adalah jawaban yang lucu - "Tidak pantas untuk logika operasi", setiap nama parameter, setiap kelas, fungsi atau apa pun yang secara logika tidak pantas ..__ Saya pikir opsi ini harus tersedia dalam bahasa pemrograman yang terhormat, dan mereka yang berpikir bahwa itu adalah tidak aman - hei, tidak ada yang bilang Anda harus menggunakannya. Mari kita ambil C #. Mereka menjatuhkan pointer tetapi hei - ada pernyataan 'kode tidak aman' - program yang Anda inginkan dengan risiko Anda sendiri.

4
Kvant

Beberapa orang mengatakan bahwa overloading operator di Jawa akan menyebabkan obsfuscation. Pernahkah orang-orang itu berhenti untuk melihat beberapa kode Java melakukan beberapa matematika dasar seperti meningkatkan nilai keuangan dengan persentase menggunakan BigDecimal? .... verbositas dari latihan semacam itu menjadi demonstrasi sendiri dari obsfuscation. Ironisnya, menambahkan overloading operator ke Java akan memungkinkan kami untuk membuat kelas Mata Uang kami sendiri yang akan membuat kode matematika seperti itu elegan dan sederhana (kurang usang).

3
Volksman

Dengan asumsi Java sebagai bahasa implementasi maka a, b, dan c semuanya akan menjadi referensi untuk mengetik Complex dengan nilai awal nol. Juga dengan anggapan bahwa Kompleks tidak dapat diubah seperti yang disebutkan BigInteger dan serupa yang tidak berubah BigDecimal , saya pikir saya maksudkan yang berikut, ketika Anda menetapkan referensi ke Kompleks yang dikembalikan dari menambahkan b dan c dan tidak membandingkan referensi ini dengan a.

Bukan:

Complex a, b, c; a = b + c;

banyak lebih sederhana dari:

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

Terkadang akan menyenangkan untuk memiliki kelebihan operator, kelas teman dan banyak warisan.

Namun saya masih berpikir itu adalah keputusan yang bagus. Jika Java memiliki operator overloading maka kita tidak pernah bisa memastikan makna operator tanpa melihat melalui kode sumber. Saat ini itu tidak perlu. Dan saya pikir contoh Anda menggunakan metode bukan overloading operator juga cukup mudah dibaca. Jika Anda ingin memperjelas hal-hal yang Anda bisa selalu menambahkan komentar di atas pernyataan berbulu.

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

Alternatif untuk Dukungan Asli Java Overloading Operator

Karena Java tidak memiliki kelebihan operator, berikut adalah beberapa alternatif yang dapat Anda perhatikan:

  1. Gunakan bahasa lain. Keduanya Groovy dan Scala memiliki overloading operator, dan berbasis di Jawa.
  2. Gunakan Java-oo , sebuah plugin yang memungkinkan kelebihan operator di Jawa. Perhatikan bahwa BUKAN platform independen. Selain itu, ia memiliki banyak masalah, dan tidak kompatibel dengan rilis terbaru Java (mis. Java 10). ( Sumber StackOverflow Asli )
  3. Gunakan JNI , Java Native Interface, atau alternatif. Ini memungkinkan Anda untuk menulis metode C atau C++ (mungkin yang lain?) Untuk digunakan di Java. Tentu saja ini juga TIDAK platform independen.

Jika ada yang mengetahui orang lain, silakan komentar, dan saya akan menambahkannya ke daftar ini.

0
gagarwa

Ini bukan alasan yang baik untuk melarangnya tetapi alasan praktis:

Orang tidak selalu menggunakannya secara bertanggung jawab. Lihat contoh ini dari scapy library Python:

>>> 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 |>>

Berikut penjelasannya:

Operator/telah digunakan sebagai operator komposisi antara dua lapisan. Ketika melakukan itu, lapisan bawah dapat memiliki satu atau lebih nya. bidang default kelebihan beban menurut lapisan atas. (Anda masih Dapat memberikan nilai yang Anda inginkan). String dapat digunakan sebagai lapisan mentah.

0
Sarien