Metode default menambahkan fitur baru yang sangat bagus ke set instruksi JVM. Setelah menggunakan metode default, jika metode baru ditambahkan ke antarmuka di pustaka, kelas pengguna yang mengimplementasikan antarmuka ini dapat secara otomatis mendapatkan implementasi default dari metode ini. Setelah pengguna ingin memperbarui kelas implementasinya, unggul saja metode default ini, dan gantinya dengan implementasi yang membuat lebih bermakna dalam skenario tertentu. Yang lebih baik adalah bahwa pengguna dapat memanggil implementasi default antarmuka dalam metode penulisan ulang untuk menambahkan beberapa fungsi tambahan.
Semuanya cukup bagus sejauh ini. Namun, menambahkan metode default ke antarmuka Java yang ada dapat menyebabkan ketidakcocokan kode . Mudah dimengerti dengan melihat contoh. Misalkan ada perpustakaan yang mengharuskan pengguna untuk mengimplementasikan salah satu antarmuka sebagai input:
antarmuka SimpleInput {void foo (); void bar ();} abstrak kelas abstrak SimpleInputAdapter mengimplementasikan SimpleInput {@Override public void bar () {// Beberapa perilaku default ...}}Sebelum Java 8, kombinasi antarmuka di atas dan kelas adaptor yang sesuai adalah pola yang sangat umum dalam bahasa Java. Pengembang Perpustakaan Kelas menyediakan adaptor untuk mengurangi jumlah pengkodean untuk konsumen perpustakaan. Namun, tujuan menyediakan antarmuka ini sebenarnya adalah untuk mencapai hubungan yang mirip dengan warisan berganda.
Mari kita asumsikan bahwa pengguna menggunakan adaptor ini:
kelas myInput memperluas SimpleInputAdapter {@Override public void foo () {// lakukan sesuatu ...} @Override public void bar () {super.bar (); // Lakukan sesuatu juga ...}}Dengan implementasi ini, pengguna dapat berinteraksi dengan perpustakaan. Perhatikan bagaimana implementasi ini menimpa metode batang untuk menambahkan fungsionalitas tambahan ke implementasi default.
Jadi apa yang akan terjadi jika perpustakaan ini dimigrasikan ke Java 8? Pertama -tama, perpustakaan ini kemungkinan akan membuang kelas adaptor dan memigrasikan fungsi ini ke metode default. Pada akhirnya, antarmuka ini akan terlihat seperti ini:
antarmuka SimpleInput {void foo (); batang void default () {// Beberapa perilaku default}}}Dengan antarmuka baru ini, pengguna harus memperbarui kodenya untuk menggunakan metode default ini alih -alih kelas adaptor. Salah satu manfaat besar menggunakan antarmuka baru alih -alih kelas adaptor adalah bahwa pengguna dapat mewarisi kelas lain alih -alih kelas adaptor ini. Mari kita mulai dengan berlatih dan mengubah kelas MyInput menjadi menggunakan metode default. Karena kami sekarang dapat mewarisi kelas lain, kami akan mencoba memperpanjang kelas dasar pihak ketiga tambahan. Apa yang dilakukan kelas dasar ini tidak penting di sini. Mari kita asumsikan bahwa ini masuk akal untuk kasus penggunaan kita.
Class MyInput memperluas ThirdPartyBaseClass mengimplementasikan SimpleInput {@Override public void foo () {// lakukan sesuatu ...} @Override public void bar () {SimpleInput.super.foo (); // Lakukan sesuatu juga ...}}Untuk mencapai fungsi yang sama dengan kelas asli, kami menggunakan sintaks Java 8 baru untuk memanggil metode default antarmuka. Demikian pula, kami memasukkan logika Method ke dalam kelas dasar myBase. Anda dapat bersantai setelah memukul bahu Anda. Itu luar biasa setelah refactoring!
Perpustakaan yang kami gunakan ini sangat ditingkatkan. Namun, personel pemeliharaan perlu menambahkan antarmuka lain untuk mengimplementasikan beberapa fungsi tambahan. Antarmuka ini disebut CompexInput, yang mewarisi kelas SimpleInput dan menambahkan metode tambahan. Karena umumnya diyakini bahwa metode default dapat ditambahkan dengan percaya diri, staf pemeliharaan mengganti metode default kelas SimpleInput dan menambahkan beberapa tindakan tambahan untuk memberikan pengguna implementasi default yang lebih baik. Bagaimanapun, ini sangat umum saat menggunakan kelas adaptor:
antarmuka ComplexInput memperluas SimpleInput {void qox (); @Override Default void bar () {SimpleInput.super.bar (); // sangat rumit, kita perlu melakukan lebih banyak ...}}Fitur baru ini terlihat sangat bagus, sehingga pengelola kelas ketiga PartyBaseClass juga memutuskan untuk menggunakan perpustakaan ini. Untuk mencapai hal ini, ia menerapkan kelas Pihak KetigaBaseClass ke antarmuka ComplexInput.
Tapi apa artinya ini bagi kelas myInput? Karena mewarisi kelas Pihak KetigaBaseClass, antarmuka ComplexInput diimplementasikan secara default. Dengan cara ini, memanggil metode default SimpleInput tidak legal. Hasilnya adalah kode pengguna tidak dapat dikompilasi pada akhirnya. Juga, metode ini benar-benar tidak mungkin dihubungi, karena Java mempertimbangkan metode super-super ini untuk memanggil kelas induk tidak langsung ilegal. Anda hanya dapat memanggil metode default antarmuka ComplexInput. Namun, ini pertama mengharuskan Anda untuk mengimplementasikan antarmuka ini secara eksplisit di kelas MyInput. Untuk pengguna perpustakaan ini, perubahan ini sama sekali tidak terduga.
(Catatan: Sederhananya, sebenarnya:
Antarmuka A {default void test () {}} antarmuka B memperluas {default void test () {}} Tes kelas publik mengimplementasikan b {public void test () {b.super.test (); //A.super.test (); Kesalahan}}Tentu saja, jika Anda menulis ini, pengguna secara aktif memilih untuk mengimplementasikan antarmuka B. Contoh dalam artikel tersebut memperkenalkan kelas dasar, sehingga perubahan yang tampaknya tidak berbahasa tidak dilakukan di perpustakaan dan kelas dasar, tetapi pada kenyataannya itu menyebabkan kode pengguna tidak dapat dikompilasi)
Anehnya, Java tidak membedakan ini saat runtime. Validator JVM memungkinkan kelas yang dikompilasi untuk memanggil metode SimpleInput :: Foo, meskipun kelas yang dimuat mewarisi versi terbaru dari Third PartyBaseClass dan secara implisit mengimplementasikan antarmuka ComplexInput. Jika Anda ingin menyalahkan, Anda hanya bisa menyalahkan kompiler. (Catatan: Perilaku kompiler dan runtime tidak konsisten)
Jadi apa yang telah kita pelajari darinya? Sederhananya, jangan mengganti metode default dari antarmuka asli di antarmuka lain. Jangan menulis ulang dengan metode default lain, dan jangan menulis ulang dengan beberapa metode abstrak. Singkatnya, Anda harus sangat berhati -hati saat menggunakan metode default. Meskipun mereka membuat antarmuka perpustakaan koleksi Java yang ada lebih mudah ditingkatkan, ini memungkinkan Anda untuk membuat panggilan metode dalam struktur warisan kelas, yang pada dasarnya meningkatkan kompleksitas. Sebelum Java 7, Anda hanya perlu melintasi hierarki kelas linier dan melihat kode panggilan yang sebenarnya. Ketika Anda merasa benar -benar membutuhkannya, gunakan metode default.
Di atas adalah penjelasan terperinci tentang mengapa Anda harus menggunakan metode default Java 8 dengan hati -hati. Saya berharap ini akan membantu untuk pembelajaran semua orang.