Apa alasan bagus untuk melarang pewarisan di Jawa, misalnya dengan menggunakan kelas akhir atau kelas menggunakan konstruktor tanpa parameter pribadi? Apa alasan bagus membuat metode menjadi final?
Apa alasan bagus untuk melarang pewarisan di Jawa, misalnya dengan menggunakan kelas akhir atau kelas menggunakan konstruktor tanpa parameter pribadi? Apa alasan bagus membuat metode menjadi final?
Jawaban:
Referensi terbaik Anda di sini adalah Butir 19 dari buku luar biasa Joshua Bloch "Java Efektif", yang disebut "Desain dan dokumen untuk warisan atau melarangnya". (Ini item 17 di edisi kedua dan item 15 di edisi pertama.) Anda harus benar-benar membacanya, tetapi saya akan meringkasnya.
Interaksi kelas yang diwariskan dengan orang tua mereka dapat mengejutkan dan tidak dapat diprediksi jika leluhur tidak dirancang untuk diwarisi.
Kelas karenanya harus datang dalam dua jenis:
Kelas dirancang untuk diperpanjang , dan dengan dokumentasi yang cukup untuk menggambarkan bagaimana hal itu harus dilakukan
Kelas ditandai final
Jika Anda menulis kode internal murni ini mungkin sedikit berlebihan. Namun upaya ekstra yang terlibat dalam menambahkan lima karakter ke file kelas sangat kecil. Jika Anda menulis hanya untuk konsumsi internal, maka pembuat kode di masa depan selalu dapat menghapus 'final' - Anda dapat menganggapnya sebagai peringatan yang mengatakan "kelas ini tidak dirancang dengan mempertimbangkan warisan".
Anda mungkin ingin membuat metode final agar kelas utama tidak bisa mengubah perilaku yang dihitung dalam metode lain. Metode yang disebut konstruktor sering dinyatakan final sehingga Anda tidak mendapatkan kejutan yang tidak menyenangkan saat membuat objek.
final
.
Salah satu alasan untuk membuat final kelas adalah jika Anda ingin memaksakan komposisi atas warisan. Ini umumnya diinginkan dalam menghindari kopling ketat antar kelas.
Ada 3 kasus penggunaan di mana Anda dapat pergi untuk metode terakhir.
Tujuan membuat final kelas:
Sehingga tidak ada yang bisa memperpanjang kelas-kelas itu dan mengubah perilaku mereka.
Contoh: Integer kelas Wrapper adalah kelas akhir. Jika kelas itu belum final, maka siapa pun dapat memperluas Integer ke kelasnya sendiri dan mengubah perilaku dasar kelas integer. Untuk menghindari hal ini, java membuat semua kelas pembungkus sebagai kelas akhir.
DerivedInteger
, itu masih tidak mengubah kelas Integer asli, dan siapa pun yang menggunakannya DerivedInteger
melakukannya dengan risiko sendiri, jadi saya masih tidak mengerti mengapa itu menjadi masalah.
Anda mungkin ingin membuat objek yang tidak dapat diubah ( http://en.wikipedia.org/wiki/Immutable_object ), Anda mungkin ingin membuat singleton ( http://en.wikipedia.org/wiki/Singleton_pattern ), atau Anda mungkin ingin untuk mencegah seseorang mengganti metode untuk alasan efisiensi, keselamatan, atau keamanan.
Warisan seperti gergaji mesin - sangat kuat, tetapi mengerikan di tangan yang salah. Entah Anda merancang kelas untuk diwarisi (yang dapat membatasi fleksibilitas dan membutuhkan waktu lebih lama) atau Anda harus melarangnya.
Lihat Java Edisi ke-2 yang efektif, item 16 dan 17, atau posting blog saya "Pajak Warisan" .
Hmmm ... Saya bisa memikirkan dua hal:
Anda mungkin memiliki kelas yang membahas masalah keamanan tertentu. Dengan mensubclassingnya dan memberi makan sistem Anda versi subclassenya, penyerang dapat menghindari batasan keamanan. Misalnya aplikasi Anda mungkin mendukung plugin dan jika sebuah plugin hanya dapat mensubklasifikasikan kelas keamanan Anda yang relevan, ia dapat menggunakan trik ini untuk menyelundupkan versi subclassnya ke tempatnya. Namun, ini adalah sesuatu yang harus dihadapi Sun mengenai applet dan sejenisnya, mungkin bukan kasus yang realistis.
Yang jauh lebih realistis adalah untuk menghindari objek menjadi bisa berubah. Misalnya, karena String tidak dapat diubah, kode Anda dapat menyimpan referensi dengan aman
String blah = someOtherString;
alih-alih menyalin string terlebih dahulu. Namun, jika Anda dapat mensubkripsikan String, Anda dapat menambahkan metode ke dalamnya yang memungkinkan nilai string untuk dimodifikasi, sekarang tidak ada kode yang dapat mengandalkan lagi bahwa string akan tetap sama jika hanya menyalin string seperti di atas, alih-alih harus menduplikasi tali.
Jika Anda menandai kelas dan metode sebagai final, Anda mungkin melihat kenaikan kinerja kecil, karena runtime tidak harus mencari metode kelas yang tepat untuk memanggil objek tertentu. Metode non-final ditandai sebagai virtual sehingga dapat diperluas dengan benar jika diperlukan, metode final dapat langsung dihubungkan atau dikompilasi secara inline di kelas.
Untuk menghentikan orang dari melakukan hal-hal yang dapat membingungkan diri sendiri dan orang lain. Bayangkan sebuah perpustakaan fisika di mana Anda memiliki konstanta atau perhitungan yang pasti. Tanpa menggunakan kata kunci terakhir, seseorang dapat datang dan mendefinisikan kembali perhitungan dasar atau konstanta yang TIDAK PERNAH berubah.
Anda ingin membuat metode final agar kelas utama tidak mengubah perilakunya. Ketika Anda ingin dapat mengubah perilaku, buat metode ini untuk umum. Saat Anda mengganti metode publik, metode itu dapat diubah.