Saya tidak tahu tentang semua bahasa pemrograman, tetapi jelas bahwa biasanya kemungkinan overloading metode dengan mempertimbangkan jenis kembalinya (dengan asumsi argumennya adalah jumlah dan jenis yang sama) tidak didukung.
Maksud saya sesuatu seperti ini:
int method1 (int num)
{
}
long method1 (int num)
{
}
Ini bukan masalah besar untuk pemrograman tetapi pada beberapa kesempatan saya akan menyambutnya.
Jelas tidak akan ada cara bagi bahasa-bahasa tersebut untuk mendukung itu tanpa ada cara untuk membedakan metode apa yang sedang dipanggil, tetapi sintaks untuk itu dapat sesederhana sesuatu seperti [int] method1 (num) atau [long] method1 (num) dengan cara itu kompiler akan tahu mana yang akan dipanggil.
Saya tidak tahu tentang bagaimana kompiler bekerja tetapi itu tampaknya tidak terlalu sulit untuk dilakukan, jadi saya bertanya-tanya mengapa hal seperti itu biasanya tidak dilaksanakan.
Apa alasan mengapa hal seperti itu tidak didukung?
sumber
Foo
danBar
.Jawaban:
Ini menyulitkan pengecekan tipe.
Ketika Anda hanya mengizinkan overloading berdasarkan tipe argumen, dan hanya mengizinkan deduksi tipe variabel dari inisialisasi mereka, semua informasi tipe Anda mengalir dalam satu arah: naik pohon sintaks.
Saat Anda mengizinkan informasi jenis untuk bepergian di kedua arah, seperti menyimpulkan tipe variabel dari penggunaannya, Anda memerlukan pemecah kendala (seperti Algoritma W, untuk sistem tipe Hindley-Milner) untuk menentukan jenisnya.
Di sini, kita perlu meninggalkan tipe
x
sebagai variabel tipe yang tidak terselesaikan∃T
, di mana yang kita tahu adalah bahwa itu dapat diuraikan. Hanya nanti, ketikax
digunakan pada tipe konkret, kita memiliki cukup informasi untuk menyelesaikan kendala dan menentukan itu∃T = int
, yang menyebarkan informasi tipe ke bawah pohon sintaks dari ekspresi panggilan kex
.Jika kami gagal menentukan jenisnya
x
, kode ini akan kelebihan beban juga (jadi pemanggil akan menentukan jenisnya) atau kami harus melaporkan kesalahan tentang ambiguitas.Dari sini, seorang perancang bahasa dapat menyimpulkan:
Ini menambah kompleksitas implementasi.
Itu membuat pemeriksaan ketik lebih lambat — dalam kasus patologis, secara eksponensial terjadi.
Lebih sulit menghasilkan pesan kesalahan yang baik.
Itu terlalu berbeda dari status quo.
Saya tidak merasa ingin mengimplementasikannya.
sumber
Karena ambigu. Menggunakan C # sebagai contoh:
Kelebihan mana yang harus kita gunakan?
Ok, mungkin itu agak tidak adil. Kompiler tidak dapat mengetahui jenis apa yang akan digunakan jika kami tidak memberitahukannya dalam bahasa hipotetis Anda. Jadi, pengetikan tersirat tidak mungkin dalam bahasa Anda dan ada metode anonim dan Linq bersama dengannya ...
Bagaimana dengan yang ini? (Tanda tangan sedikit didefinisikan ulang untuk menggambarkan titik.)
Haruskah kita menggunakan
int
kelebihan, ataushort
kelebihan? Kami tidak tahu, kami harus menentukannya dengan[int] method1(num)
sintaks Anda . Yang agak menyakitkan untuk diurai dan menulis jujur.Masalahnya, sintaksisnya mirip dengan metode generik dalam C #.
(C ++ dan Java memiliki fitur serupa.)
Singkatnya, perancang bahasa memilih untuk memecahkan masalah dengan cara yang berbeda untuk menyederhanakan penguraian dan mengaktifkan fitur bahasa yang jauh lebih kuat.
Anda mengatakan Anda tidak tahu banyak tentang kompiler. Saya sangat merekomendasikan belajar tentang tata bahasa dan parser. Setelah Anda memahami apa itu tata bahasa bebas konteks, Anda akan memiliki ide yang lebih baik tentang mengapa ambiguitas adalah hal yang buruk.
sumber
short
danint
.method
mengembalikan pendek atau int, dan jenisnya didefinisikan sebagai panjang.long
/int
/short
lebih tentang kompleksitas subtyping dan / atau konversi implisit daripada tentang kelebihan tipe pengembalian. Setelah semua, jumlah literal yang kelebihan beban pada jenis mereka kembali di C ++, Java, C♯, dan banyak lainnya, dan bahwa tampaknya tidak ada masalah. Anda dapat membuat aturan: misalnya memilih jenis yang paling spesifik / umum.Semua fitur bahasa menambah kompleksitas, sehingga mereka harus memberikan manfaat yang cukup untuk membenarkan gotcha yang tak terhindarkan, kasing sudut, dan kebingungan pengguna yang dibuat oleh setiap fitur. Untuk sebagian besar bahasa, yang satu ini tidak memberikan manfaat yang cukup untuk membenarkannya.
Dalam sebagian besar bahasa, Anda akan mengharapkan ekspresi
method1(2)
memiliki tipe yang pasti dan nilai pengembalian yang lebih atau kurang dapat diprediksi. Tetapi jika Anda mengizinkan overloading pada nilai yang dikembalikan, itu berarti tidak mungkin untuk mengatakan apa arti ekspresi itu secara umum tanpa mempertimbangkan konteks di sekitarnya. Pertimbangkan apa yang terjadi ketika Anda memilikiunsigned long long foo()
metode yang implementasinya berakhirreturn method1(2)
? Haruskah yang memanggillong
-returning overload atauint
-returning overload atau hanya memberikan kesalahan kompilator?Plus, jika Anda harus membantu kompiler dengan membubuhi keterangan tipe pengembalian, Anda tidak hanya menciptakan lebih banyak sintaks (yang meningkatkan semua biaya yang disebutkan untuk memungkinkan fitur ada sama sekali), tetapi Anda secara efektif melakukan hal yang sama seperti membuat dua metode dengan nama berbeda dalam bahasa "normal". Apakah
[long] method1(2)
lebih intuitif daripadalong_method1(2)
?Di sisi lain, beberapa bahasa fungsional seperti Haskell dengan sistem tipe statis yang sangat kuat memungkinkan perilaku semacam ini, karena inferensi tipe mereka cukup kuat sehingga Anda jarang perlu membuat anotasi jenis pengembalian dalam bahasa tersebut. Tapi itu hanya mungkin karena bahasa-bahasa itu benar-benar menegakkan keamanan jenis, lebih dari bahasa tradisional mana pun, bersama dengan mengharuskan semua fungsi menjadi murni dan transparan referensial. Itu bukan sesuatu yang akan layak di sebagian besar bahasa OOP.
sumber
Hal ini tersedia dalam Swift dan bekerja dengan baik di sana. Jelas Anda tidak dapat memiliki tipe ambigu di kedua sisi sehingga harus diketahui di sebelah kiri.
Saya menggunakan ini dalam penyandian sederhana / decode API .
Itu berarti panggilan di mana tipe parameter diketahui, seperti
init
objek, bekerja sangat sederhana:Jika Anda memperhatikan dengan seksama, Anda akan melihat
dechOpt
panggilan di atas. Saya menemukan cara sulit bahwa membebani nama fungsi yang sama di mana pembeda mengembalikan opsi terlalu rentan terhadap kesalahan karena konteks panggilan dapat memperkenalkan harapan itu adalah opsional.sumber
sumber
var1
dan melanjutkan dengan tipe inferensi dan segera setelah beberapa ekspresi lain menentukan jenisvar1
penggunaan yang untuk memilih implementasi yang tepat. Pada intinya, menunjukkan kasus di mana inferensi tipe non-sepele jarang membuktikan titik selain inferensi tipe umumnya non-sepele.method1
harus dinyatakan untuk mengembalikan jenis tertentu.