Penalaran tentang apakah pewarisan (atau fitur tunggal, benar-benar) diperlukan atau tidak tanpa juga mempertimbangkan sisa bahasa semantik tidak ada gunanya; Anda berdebat dalam ruang hampa.
Yang Anda butuhkan adalah filosofi desain bahasa yang konsisten; bahasa harus mampu menyelesaikan masalah secara elegan. Model untuk mencapai ini mungkin atau mungkin tidak memerlukan warisan, tetapi sulit untuk menilai ini tanpa gambaran besar.
Jika, misalnya, bahasa Anda memiliki fungsi kelas satu, aplikasi fungsi parsial, tipe data polimorfik, variabel tipe dan tipe generik, Anda telah cukup banyak membahas basis yang sama seperti yang Anda miliki dengan warisan OOP klasik, tetapi menggunakan paradigma yang berbeda.
Jika Anda memiliki pengikatan yang terlambat, pengetikan dinamis, metode-sebagai-properti, argumen fungsi fleksibel, dan fungsi kelas satu, Anda juga membahas alasan yang sama, tetapi sekali lagi, menggunakan paradigma yang berbeda.
(Menemukan contoh untuk dua paradigma yang diuraikan dibiarkan sebagai latihan untuk pembaca.)
Jadi, pikirkan tentang jenis semantik yang Anda inginkan, bermain-main dengan mereka dan lihat apakah mereka cukup tanpa warisan. Jika tidak, Anda dapat memutuskan untuk memasukkan warisan ke dalam campuran, atau Anda dapat memutuskan bahwa ada sesuatu yang hilang.
Ya, ini adalah keputusan desain yang masuk akal untuk menghilangkan warisan.
Sebenarnya ada alasan yang sangat baik untuk menghapus warisan implementasi, karena dapat menghasilkan beberapa kode yang sangat kompleks dan sulit untuk dipelihara. Saya bahkan lebih jauh menganggap warisan (seperti yang biasanya diterapkan di sebagian besar bahasa OOP) sebagai kesalahan.
Clojure, misalnya, tidak menyediakan warisan implementasi, lebih memilih untuk menyediakan serangkaian fitur ortogonal (protokol, data, fungsi, makro) yang dapat digunakan untuk mencapai hasil yang sama tetapi jauh lebih bersih.
Berikut adalah video yang saya temukan sangat mencerahkan tentang topik umum ini, di mana Rich Hickey mengidentifikasi sumber mendasar kompleksitas dalam bahasa pemrograman (termasuk warisan) dan menyajikan alternatif untuk masing-masing: Sederhana menjadi mudah
sumber
Ketika saya pertama kali menemukan fakta bahwa kelas VB6 tidak mendukung warisan (hanya antarmuka), itu benar-benar membuat saya kesal (dan masih).
Namun, alasannya sangat buruk adalah karena tidak memiliki parameter konstruktor juga, jadi Anda tidak bisa melakukan injeksi ketergantungan normal (DI). Jika Anda memiliki DI maka itu lebih penting daripada warisan karena Anda dapat mengikuti prinsip komposisi yang disukai daripada warisan. Itu cara yang lebih baik untuk menggunakan kembali kode.
Tidak memiliki Mixin? Jika Anda ingin mengimplementasikan antarmuka dan mendelegasikan semua pekerjaan antarmuka itu ke objek yang ditetapkan melalui injeksi dependensi, maka Mixin sangat ideal. Kalau tidak, Anda harus menulis semua kode boilerplate untuk mendelegasikan setiap metode dan / atau properti ke objek anak. Saya melakukannya banyak (terima kasih kepada C #) dan itu satu hal yang saya harap tidak perlu saya lakukan.
sumber
Untuk tidak setuju dengan jawaban lain: tidak, Anda membuang fitur ketika mereka tidak kompatibel dengan sesuatu yang Anda inginkan lebih. Java (dan bahasa-bahasa GC'd lainnya) membuang manajemen memori eksplisit karena ia ingin mengetik lebih aman. Haskell membuang mutasi karena ingin lebih banyak alasan rasional dan suka jenis. Bahkan C membuang (atau menyatakan ilegal) jenis aliasing dan perilaku lainnya karena ia ingin lebih mengoptimalkan kompiler.
Jadi pertanyaannya adalah: Apa yang Anda inginkan lebih dari sekadar warisan?
sumber
free
/delete
operasi memberi Anda kemampuan untuk membatalkan referensi; kecuali sistem tipe Anda dapat melacak semua referensi yang terpengaruh, itu membuat bahasa tidak aman. Secara khusus, C atau C ++ tidak aman. Memang benar bahwa Anda dapat membuat kompromi dalam satu atau yang lain (misalnya tipe linier atau batasan alokasi) untuk membuat mereka setuju. Lebih tepatnya saya seharusnya mengatakan bahwa Java menginginkan keamanan jenis dengan sistem tipe khusus yang sederhana dan alokasi tidak terbatas lebih banyak.null
referensi). Laranganfree
adalah pembatasan tambahan yang cukup sewenang-wenang. Singkatnya, apakah suatu bahasa adalah tipe aman tergantung pada definisi Anda tentang keamanan jenis daripada pada bahasa.T
referensi merujuk pada salah satunull
atau objek kelas yang diperluasT
;null
jelek, tetapi operasinull
melempar pengecualian yang jelas daripada merusak tipe invarian di atas. Kontras dengan C ++: setelah panggilan kedelete
,T*
pointer mungkin menunjuk ke memori yang tidak lagi memegangT
objek. Lebih buruk lagi, melakukan penugasan bidang menggunakan penunjuk itu dalam penugasan, Anda mungkin memperbarui bidang objek yang sama sekali berbeda dari kelas jika kebetulan ditempatkan di alamat terdekat. Itu bukan tipe keselamatan oleh definisi istilah yang berguna.Tidak.
Jika Anda ingin menghapus fitur bahasa dasar, maka Anda secara universal menyatakan bahwa itu tidak pernah diperlukan (atau sulit untuk diimplementasikan secara tidak adil, yang tidak berlaku di sini). Dan "tidak pernah" adalah kata yang kuat dalam rekayasa perangkat lunak. Anda akan membutuhkan pembenaran yang sangat kuat untuk membuat pernyataan seperti itu.
sumber
Berbicara dari perspektif C ++ yang ketat, pewarisan berguna untuk dua tujuan utama:
Untuk poin 1 selama Anda memiliki beberapa cara untuk berbagi kode tanpa harus terlalu banyak berakrobat, Anda dapat menghapus warisan. Untuk poin 2. Anda bisa menggunakan cara java dan bersikeras antarmuka untuk mengimplementasikan fitur ini.
Manfaat menghapus warisan adalah
Pengorbanan sebagian besar antara "Dont Repeat Yourself" dan Fleksibilitas di satu sisi dan penghindaran masalah di sisi lain. Secara pribadi saya akan benci untuk melihat warisan dari C ++ hanya karena beberapa pengembang lain mungkin tidak cukup pintar untuk melihat masalah.
sumber
Anda dapat melakukan banyak pekerjaan yang sangat berguna tanpa implementasi warisan atau mixin, tapi saya ingin tahu apakah Anda harus memiliki beberapa jenis antarmuka warisan, yaitu, deklarasi yang mengatakan jika suatu objek mengimplementasikan antarmuka A maka ia juga perlu antarmuka B (yaitu, A adalah spesialisasi B dan ada jenis hubungan). Di sisi lain, objek Anda yang dihasilkan hanya perlu merekam bahwa ia mengimplementasikan kedua antarmuka, sehingga tidak ada terlalu banyak kerumitan di sana. Semua bisa dilakukan dengan sempurna.
Kurangnya warisan implementasi memiliki satu kelemahan jelas: Anda tidak akan dapat membangun vtables yang diindeks numerik untuk kelas Anda dan karenanya harus melakukan pencarian hash untuk setiap pemanggilan metode (atau mencari cara cerdas untuk menghindarinya). Ini bisa menyakitkan jika Anda merutekan nilai fundamental (misalnya, angka) melalui mekanisme ini. Bahkan implementasi hash yang sangat baik bisa mahal ketika Anda menekannya berkali-kali di setiap loop batin!
sumber