Sudah umum diterima bahwa generik Java gagal dalam beberapa hal penting. Kombinasi kartu liar dan batas menyebabkan beberapa kode serius tidak dapat dibaca.
Namun, ketika saya melihat bahasa lain, saya benar-benar tidak bisa menemukan sistem tipe generik yang disukai oleh para programmer.
Jika kami mengambil yang berikut sebagai sasaran desain sistem tipe seperti itu:
- Selalu menghasilkan deklarasi tipe yang mudah dibaca
- Mudah dipelajari (tidak perlu memoles kovarians, contravariance, dll.)
- memaksimalkan jumlah kesalahan waktu kompilasi
Apakah ada bahasa yang benar? Jika saya google, satu-satunya hal yang saya lihat adalah keluhan tentang bagaimana sistem jenis mengisap dalam bahasa X. Apakah kompleksitas semacam ini melekat dalam pengetikan generik? Haruskah kita menyerah untuk mencoba memverifikasi keamanan tipe 100% pada waktu kompilasi?
Pertanyaan utama saya adalah bahasa mana yang “paling benar” yang terbaik sehubungan dengan ketiga tujuan ini. Saya menyadari bahwa itu subjektif, tetapi sejauh ini saya bahkan tidak dapat menemukan satu bahasa di mana tidak semua programmer setuju bahwa sistem tipe generik berantakan.
Tambahan: seperti yang disebutkan, kombinasi subtyping / inheritance dan generik adalah yang menciptakan kompleksitas, jadi saya benar-benar mencari bahasa yang menggabungkan keduanya dan menghindari ledakan kompleksitas.
sumber
easy-to-read type declarations
? Kriteria ketiga juga ambigu: misalnya, saya dapat mengubah indeks array dari batas menjadi kesalahan waktu kompilasi dengan tidak membiarkan Anda indeks array kecuali saya dapat menghitung indeks pada waktu kompilasi. Juga, kriteria kedua mengesampingkan subtyping. Itu tidak selalu merupakan hal yang buruk tetapi Anda harus menyadari apa yang Anda minta.Foo<T> where SiameseCat:T
) dan bahwa tidak ada kemungkinan memiliki tipe generik yang tidak dapat dikonversiObject
. IMHO, .NET akan mendapat manfaat dari tipe agregat yang mirip dengan struktur, tetapi bahkan lebih bertulang. JikaKeyValuePair<TKey,TValue>
jenis seperti itu, maka sebuahIEnumerable<KeyValuePair<SiameseCat,FordFocus>>
dapat dilemparkan keIEnumerable<KeyValuePair<Animal,Vehicle>>
, tetapi hanya jika jenisnya tidak bisa kotak.Jawaban:
Sementara Generik telah menjadi arus utama dalam komunitas pemrograman fungsional selama beberapa dekade, menambahkan generik ke bahasa pemrograman berorientasi objek menawarkan beberapa tantangan unik, khususnya interaksi subtyping dan generik.
Namun, bahkan jika kita fokus pada bahasa pemrograman berorientasi objek, dan Java khususnya, sistem generik yang jauh lebih baik dapat dirancang:
Jenis generik harus diterima di mana pun jenis lainnya. Secara khusus, jika
T
adalah parameter tipe, ekspresi berikut harus dikompilasi tanpa peringatan:Ya, ini membutuhkan obat generik untuk diverifikasi, sama seperti setiap jenis bahasa lainnya.
Kovarian dan contravariance dari tipe generik harus ditentukan dalam (atau disimpulkan dari) deklarasi, daripada setiap kali tipe generik digunakan, sehingga kita dapat menulis
daripada
Karena tipe generik dapat menjadi agak lama, kita tidak perlu menentukannya secara berlebihan. Artinya, kita harus bisa menulis
daripada
Jenis apa pun harus diterima sebagai parameter tipe, bukan hanya tipe referensi. (Jika kita dapat memiliki
int[]
, mengapa kita tidak dapat memilikiList<int>
)?Semua ini dimungkinkan dalam C #.
sumber
Penggunaan subtipe menciptakan banyak komplikasi ketika melakukan pemrograman generik. Jika Anda bersikeras menggunakan bahasa dengan subtipe, Anda harus menerima ada kompleksitas inheren tertentu dalam pemrograman generik yang menyertainya. Beberapa bahasa melakukannya lebih baik daripada yang lain, tetapi Anda hanya bisa mengambil sejauh ini.
Bandingkan dengan generik Haskell, misalnya. Mereka cukup sederhana sehingga jika Anda menggunakan tipe inferensi, Anda dapat menulis fungsi generik yang benar secara tidak sengaja . Bahkan, jika Anda menentukan jenis tunggal, compiler sering berkata kepada dirinya sendiri, "Yah, aku sedang akan membuat ini generik, tetapi Anda meminta saya untuk membuatnya hanya untuk ints, jadi apa pun."
Diakui, orang menggunakan sistem tipe Haskell dalam beberapa cara yang sangat rumit, menjadikannya kutukan bagi setiap pemula, tetapi sistem tipe yang mendasarinya sendiri elegan dan sangat dikagumi.
sumber
a
harus semacam integer".Ada sedikit riset dalam menggabungkan obat generik dengan subtyping yang terjadi sekitar 20 tahun yang lalu. Bahasa pemrograman Thor yang dikembangkan oleh kelompok riset Barbara Liskov di MIT memiliki gagasan tentang klausa "di mana" yang memungkinkan Anda menentukan persyaratan jenis yang Anda parameterkan. (Ini mirip dengan apa yang C ++ coba lakukan dengan Konsep .)
Makalah yang menggambarkan generik Thor dan bagaimana mereka berinteraksi dengan subtipe Thor adalah: Day, M; Gruber, R; Liskov, B; Myers, AC: Subtipe vs. klausa mana: membatasi polimorfisme parametrik , ACM Conf pada Obj-Oriented Prog, Sys, Lang dan Apps , (OOPSLA-10): 156-158, 1995.
Saya percaya mereka, pada gilirannya, dibangun di atas pekerjaan yang dilakukan di Emerald selama akhir 1980-an. (Saya belum membaca karya itu, tetapi rujukannya adalah: Hitam, A; Hutchinson, N; Jul, E; Levy, H; Carter, L: Distribusi dan Jenis Abstrak di Emerald , _IEEE T. Software Eng., 13 ( 1): 65-76, 1987.
Baik Thor maupun Emerald adalah "bahasa akademik" sehingga mereka mungkin tidak mendapatkan penggunaan yang cukup bagi orang-orang untuk benar-benar memahami apakah klausa (konsep) benar-benar memecahkan masalah nyata. Sangat menarik untuk membaca artikel Bjarne Stroustrup tentang mengapa percobaan pertama di Concepts in C ++ gagal: Stroustrup, B: Keputusan C ++ 0x "Remove Concepts" , Dr Dobbs , 22 Juli 2009. (Info lebih lanjut tentang halaman muka Stroustrup . )
Arah lain yang tampaknya orang coba adalah sesuatu yang disebut ciri . Misalnya bahasa pemrograman Rust Mozilla menggunakan ciri-ciri. Seperti yang saya pahami (yang mungkin benar-benar salah), menyatakan bahwa suatu kelas memuaskan suatu sifat sangat mirip dengan mengatakan bahwa suatu kelas mengimplementasikan antarmuka, tetapi Anda mengatakan "berperilaku seperti" daripada "adalah". Tampaknya bahasa pemrograman Swift baru Apple menggunakan konsep protokol yang mirip untuk menetapkan batasan pada parameter ke generik .
sumber