Saya membaca buku tentang Java dan mengatakan bahwa Anda dapat mendeklarasikan seluruh kelas sebagai final
. Saya tidak bisa memikirkan apa pun di mana saya akan menggunakan ini.
Saya baru mengenal pemrograman dan saya bertanya-tanya apakah programmer benar-benar menggunakan ini pada program mereka . Jika mereka melakukannya, kapan mereka menggunakannya sehingga saya bisa memahaminya lebih baik dan tahu kapan menggunakannya.
Jika Java berorientasi objek, dan Anda mendeklarasikan kelas final
, bukankah itu menghentikan gagasan kelas yang memiliki karakteristik objek?
Di Jawa, item dengan
final
pengubah tidak dapat diubah!Ini termasuk kelas akhir, variabel akhir, dan metode akhir:
sumber
final
pengubah tidak dapat diubah!", Terlalu kategoris dan, pada kenyataannya, tidak sepenuhnya benar. Seperti yang dikatakan Grady Booch, "Sebuah objek memiliki status, perilaku, dan identitas". Sementara kita tidak bisa mengubah identitas obyek sekali referensi telah ditandai sebagai akhir, kita memiliki kesempatan untuk mengubah nya negara dengan menetapkan nilai-nilai baru untuk non-nyafinal
bidang (asalkan, tentu saja, memiliki mereka.) Siapa saja yang berencana untuk mendapatkan Sertifikasi Java Java (seperti 1Z0-808, dll.) harus mengingat hal ini karena mungkin ada pertanyaan tentang aspek ini pada ujian ...Satu skenario di mana final penting, ketika Anda ingin mencegah warisan kelas, untuk alasan keamanan. Ini memungkinkan Anda untuk memastikan bahwa kode yang Anda jalankan tidak dapat ditimpa oleh seseorang.
Skenario lain adalah untuk optimasi: Saya sepertinya ingat bahwa kompiler Java menyatukan beberapa panggilan fungsi dari kelas akhir. Jadi, jika Anda menelepon
a.x()
dan dideklarasikanfinal
, kami tahu pada waktu kompilasi kode apa yang akan dan dapat sejalan dengan fungsi panggilan. Saya tidak tahu apakah ini benar-benar dilakukan, tetapi dengan final itu adalah suatu kemungkinan.sumber
Contoh terbaik adalah
yang merupakan kelas abadi dan tidak dapat diperpanjang. Tentu saja, ada lebih dari sekedar membuat final kelas menjadi abadi.
sumber
Bacaan yang relevan: Prinsip Terbuka-Terbuka oleh Bob Martin.
Kutipan kunci:
Kata
final
kunci adalah sarana untuk menegakkan ini di Jawa, apakah itu digunakan pada metode atau di kelas.sumber
final
membuat kelas tertutup untuk ekstensi daripada terbuka? Atau apakah saya menganggapnya terlalu harfiah?final
deklarasi kelas / metode tidak akan masuk akal jika Anda ingin kode implementasi ditutup untuk modifikasi tetapi terbuka untuk ekstensi dengan pewarisan.Jika Anda membayangkan hierarki kelas sebagai pohon (seperti di Jawa), kelas abstrak hanya bisa berupa cabang dan kelas akhir adalah yang hanya bisa berupa daun. Kelas-kelas yang termasuk dalam kategori-kategori tersebut tidak dapat berupa cabang dan daun.
Tidak ada pelanggaran prinsip OO di sini, final hanya memberikan simetri yang bagus.
Dalam praktiknya Anda ingin menggunakan final jika Anda ingin objek Anda tidak berubah atau jika Anda sedang menulis API, untuk memberi sinyal kepada pengguna API bahwa kelas tidak dimaksudkan untuk ekstensi.
sumber
Kata kunci
final
itu sendiri berarti sesuatu sudah final dan tidak boleh dimodifikasi dengan cara apa pun. Jika suatu kelas jika ditandaifinal
maka tidak dapat diperpanjang atau sub-kelas. Tetapi pertanyaannya adalah mengapa kita menandai kelasfinal
? IMO ada berbagai alasan:Saya telah mendengar bahwa kelas penandaan
final
meningkatkan efisiensi tetapi terus terang saya tidak dapat menemukan argumen ini memiliki bobot yang besar.Mungkin ya, tapi kadang-kadang itulah tujuan yang dimaksudkan. Terkadang kita melakukan itu untuk mencapai manfaat keamanan yang lebih besar, dll. Dengan mengorbankan kemampuan kelas ini untuk diperluas. Tetapi kelas final masih dapat memperpanjang satu kelas jika perlu.
Sebagai tambahan, kita harus lebih memilih komposisi daripada pewarisan dan
final
kata kunci sebenarnya membantu menegakkan prinsip ini.sumber
Hati-hati saat Anda membuat kelas "final". Karena jika Anda ingin menulis unit test untuk kelas akhir, Anda tidak dapat membuat subclass kelas akhir ini untuk menggunakan teknik pemecahan ketergantungan "Metode Subclass dan Override" yang dijelaskan dalam buku Michael C. Feathers "Bekerja Efektif dengan Legacy Code" . Dalam buku ini, Feathers berkata, "Serius, mudah untuk percaya bahwa disegel dan final adalah kesalahan yang salah, bahwa mereka seharusnya tidak pernah ditambahkan ke bahasa pemrograman. Tapi kesalahan sebenarnya ada pada kita. Ketika kita bergantung langsung pada perpustakaan yang di luar kendali kami, kami hanya meminta masalah. "
sumber
final class
dapat menghindari melanggar API publik ketika Anda menambahkan metode baruMisalkan pada versi 1 dari Anda
Base
kelas Anda yang Anda lakukan:dan klien melakukannya:
Kemudian jika dalam versi 2 Anda ingin menambahkan
method
metodeBase
:itu akan merusak kode klien.
Jika kami telah menggunakan
final class Base
sebagai gantinya, klien tidak akan dapat mewarisi, dan penambahan metode tidak akan merusak API.sumber
Jika kelas ditandai
final
, itu berarti bahwa struktur kelas tidak dapat dimodifikasi oleh sesuatu yang eksternal. Di mana ini adalah yang paling terlihat adalah ketika Anda melakukan warisan polimorfik tradisional, pada dasarnyaclass B extends A
tidak akan berhasil. Ini pada dasarnya adalah cara untuk melindungi beberapa bagian dari kode Anda (sejauh) .Untuk memperjelas, menandai kelas
final
tidak menandai bidangnyafinal
dan karenanya tidak melindungi properti objek tetapi struktur kelas yang sebenarnya.sumber
UNTUK MENGATASI MASALAH KELAS FINAL:
Ada dua cara untuk membuat kelas menjadi final. Yang pertama adalah menggunakan kata kunci akhir dalam deklarasi kelas:
Cara kedua untuk membuat final kelas adalah mendeklarasikan semua konstruktornya sebagai pribadi:
Menandai itu final akan menyelamatkan Anda dari kesulitan jika mengetahui bahwa itu adalah final, untuk menunjukkan tampilan pada kelas Tes ini. terlihat publik pada pandangan pertama.
Sayangnya, karena satu-satunya konstruktor kelas adalah privat, tidak mungkin untuk memperpanjang kelas ini. Dalam hal kelas Tes, tidak ada alasan bahwa kelas tersebut harus final. Kelas Tes adalah contoh yang baik tentang bagaimana kelas akhir implisit dapat menyebabkan masalah.
Jadi Anda harus menandainya sebagai final ketika Anda secara implisit membuat final kelas dengan menjadikannya konstruktor pribadi.
sumber
Kelas terakhir adalah kelas yang tidak bisa diperpanjang. Juga metode dapat dinyatakan sebagai final untuk menunjukkan bahwa tidak dapat diganti oleh subclass.
Mencegah kelas menjadi subkelas bisa sangat berguna jika Anda menulis API atau pustaka dan ingin menghindari diperpanjang untuk mengubah perilaku dasar.
sumber
Satu keuntungan menjaga kelas tetap final: -
Kelas string tetap final sehingga tidak ada yang bisa mengganti metode dan mengubah fungsionalitasnya. mis. tidak ada yang dapat mengubah fungsionalitas metode length (). Itu akan selalu mengembalikan panjang string.
Pengembang kelas ini tidak ingin ada yang mengubah fungsionalitas kelas ini, jadi ia menjadikannya final.
sumber
Ya, kadang-kadang Anda mungkin menginginkan ini, baik untuk alasan keamanan atau kecepatan. Ini dilakukan juga di C ++. Ini mungkin tidak yang berlaku untuk program, tetapi lebih jadi untuk kerangka kerja. http://www.glenmccl.com/perfj_025.htm
sumber
Dalam java final menggunakan kata kunci untuk kesempatan di bawah ini.
sumber
Kelas akhir tidak bisa diperpanjang. Jadi jika Anda ingin kelas berperilaku dengan cara tertentu dan jangan seseorang untuk menimpa metode (dengan kode yang mungkin kurang efisien dan lebih berbahaya), Anda dapat mendeklarasikan seluruh kelas sebagai metode final atau khusus yang Anda tidak ingin menjadi berubah.
Karena mendeklarasikan kelas tidak mencegah kelas menjadi instantiated, itu tidak berarti itu akan menghentikan kelas dari memiliki karakteristik suatu objek. Hanya saja Anda harus tetap berpegang pada metode seperti yang mereka nyatakan di kelas.
sumber
anggap FINAL sebagai "End of the line" - orang itu tidak dapat menghasilkan keturunan lagi. Jadi ketika Anda melihatnya dengan cara ini, ada banyak skenario dunia nyata yang akan Anda temui yang mengharuskan Anda untuk menandai penanda 'ujung jalur' ke kelas. Ini adalah Domain Driven Design - jika domain Anda menuntut ENTITY (kelas) yang diberikan tidak dapat membuat sub-kelas, maka tandai sebagai FINAL.
Saya harus mencatat bahwa tidak ada yang menghentikan Anda dari mewarisi kelas "harus ditandai sebagai final". Tapi itu umumnya diklasifikasikan sebagai "penyalahgunaan warisan", dan dilakukan karena paling sering Anda ingin mewarisi beberapa fungsi dari kelas dasar di kelas Anda.
Pendekatan terbaik adalah dengan melihat domain dan membiarkannya menentukan keputusan desain Anda.
sumber
Seperti yang dikatakan di atas, jika Anda ingin tidak ada yang dapat mengubah fungsionalitas metode ini maka Anda dapat mendeklarasikannya sebagai final.
Contoh: Jalur file server aplikasi untuk mengunduh / mengunggah, memisahkan string berdasarkan offset, metode seperti itu Anda dapat mendeklarasikannya Final sehingga fungsi metode ini tidak akan diubah. Dan jika Anda ingin metode akhir seperti itu di kelas yang terpisah, maka tentukan kelas itu sebagai kelas Final. Jadi kelas Final akan memiliki semua metode final, dimana metode Final dapat dideklarasikan dan didefinisikan dalam kelas non-final.
sumber
Kelas Android Looper adalah contoh praktis yang bagus untuk ini. http://developer.android.com/reference/android/os/Looper.html
Kelas Looper menyediakan fungsionalitas tertentu yang TIDAK dimaksudkan untuk diganti oleh kelas lain. Karenanya, tidak ada sub-kelas di sini.
sumber
Katakanlah Anda memiliki
Employee
kelas yang memiliki metodegreet
. Ketikagreet
metode ini disebut hanya mencetakHello everyone!
. Jadi itu adalah perilaku yang diharapkan darigreet
metodeSekarang, biarkan metode
GrumpyEmployee
subclassEmployee
dan overridegreet
seperti yang ditunjukkan di bawah ini.Sekarang dalam kode di bawah ini lihat
sayHello
metode. DibutuhkanEmployee
instance sebagai parameter dan memanggil metode sapaan berharap itu akan mengatakanHello everyone!
Tapi apa yang kita dapatkan adalahGet lost!
. Perubahan perilaku ini karenaEmployee grumpyEmployee = new GrumpyEmployee();
Situasi ini dapat dihindari jika
Employee
kelas dibuatfinal
. Bayangkan saja jumlah kekacauan yang bisa disebabkan oleh programmer yang nakal jikaString
Kelas tidak dinyatakan sebagaifinal
.sumber
Kelas akhir tidak bisa diperpanjang. Jika kita tidak perlu membuat kelas bisa diwarisi dalam java, kita bisa menggunakan pendekatan ini.
Jika kita hanya perlu membuat metode tertentu di kelas agar tidak ditimpa, kita hanya bisa meletakkan kata kunci terakhir di depannya. Di sana kelasnya masih bisa diwariskan.
sumber
Orientasi Objek bukan tentang warisan, ini tentang enkapsulasi. Dan warisan merusak enkapsulasi.
Mendeklarasikan final kelas sangat masuk akal dalam banyak kasus. Objek apa pun yang mewakili "nilai" seperti warna atau jumlah uang bisa final. Mereka berdiri sendiri.
Jika Anda menulis perpustakaan, buat kelas Anda final kecuali Anda secara eksplisit membuat mereka berasal. Kalau tidak, orang dapat menurunkan kelas Anda dan mengganti metode, melanggar asumsi / invarian Anda. Ini mungkin memiliki implikasi keamanan juga.
Joshua Bloch dalam “Java Efektif” merekomendasikan untuk mendesain secara eksplisit untuk pewarisan atau melarangnya dan ia mencatat bahwa mendesain untuk pewarisan tidak semudah itu.
sumber