Terjemahan artikel yang ditulis oleh Peter Verhas tertanggal April 2014. Dari penerjemah: istilah " metode default " baru saja muncul di Java dan saya tidak yakin apakah ada terjemahan ke dalam bahasa Rusia untuk itu. Saya akan menggunakan istilah "metode default", meskipun menurut saya itu tidak ideal. Saya mengundang Anda untuk mendiskusikan terjemahan yang lebih berhasil.
Apa metode defaultnya
Sekarang, dengan dirilisnya Java 8, Anda dapat menambahkan metode baru ke antarmuka sehingga antarmuka tetap kompatibel dengan kelas yang mengimplementasikannya. Ini sangat penting jika Anda mengembangkan perpustakaan yang digunakan oleh banyak programmer dari Kyiv hingga New York. Sebelum Java 8, jika Anda mendefinisikan antarmuka di perpustakaan, Anda tidak dapat menambahkan metode ke dalamnya tanpa risiko bahwa beberapa aplikasi yang menjalankan antarmuka Anda akan rusak saat diperbarui. Jadi, di Java 8 Anda tidak lagi takut akan hal ini? Tidak Anda tidak bisa. Menambahkan metode default ke antarmuka mungkin membuat beberapa kelas tidak dapat digunakan. Pertama-tama mari kita lihat hal-hal baik tentang metode default. Di Java 8, metode ini dapat diimplementasikan langsung di antarmuka. (Metode statis dalam sebuah antarmuka sekarang juga dapat diimplementasikan, tetapi lain ceritanya.) Metode yang diimplementasikan dalam sebuah antarmuka disebut metode default, dan dilambangkan dengan kata kunci default . Jika suatu kelas mengimplementasikan sebuah antarmuka, ia dapat, namun tidak diharuskan, mengimplementasikan metode yang diimplementasikan dalam antarmuka tersebut. Kelas mewarisi implementasi default. Inilah sebabnya mengapa tidak perlu memodifikasi kelas saat mengubah antarmuka yang diimplementasikannya.Warisan berganda?
Segalanya menjadi lebih rumit jika suatu kelas mengimplementasikan lebih dari satu (katakanlah, dua) antarmuka, dan mereka mengimplementasikan metode default yang sama. Metode mana yang akan diwarisi oleh kelas? Jawabannya adalah tidak ada. Dalam hal ini, kelas harus mengimplementasikan metode itu sendiri (baik secara langsung atau dengan mewarisinya dari kelas lain). Situasinya serupa jika hanya satu antarmuka yang memiliki metode default, dan di antarmuka lain metode yang sama bersifat abstrak. Java 8 mencoba untuk disiplin dan menghindari situasi yang ambigu. Jika metode dideklarasikan di lebih dari satu antarmuka, maka tidak ada implementasi default yang diwarisi oleh kelas - Anda akan mendapatkan kesalahan kompilasi. Meskipun demikian, Anda mungkin tidak mendapatkan kesalahan kompilasi jika kelas Anda sudah dikompilasi. Java 8 tidak cukup kuat dalam hal ini. Ada alasan mengapa saya tidak ingin membahasnya (misalnya: rilis Java sudah dirilis dan waktu diskusi sudah lama berlalu dan secara umum, ini bukan tempat yang tepat untuk mereka).- Katakanlah Anda memiliki dua antarmuka dan sebuah kelas mengimplementasikan keduanya.
- Salah satu antarmuka mengimplementasikan metode default m().
- Anda mengkompilasi semua antarmuka dan kelas.
- Anda mengubah antarmuka yang tidak memiliki metode m() dengan mendeklarasikannya sebagai metode abstrak.
- Anda hanya mengkompilasi antarmuka yang dimodifikasi.
- Mulai kelas.
- ubah antarmuka dengan metode m() abstrak dan tambahkan implementasi default.
- Kompilasi antarmuka yang dimodifikasi.
- Jalankan kelas: kesalahan.
Kode contoh
Untuk mendemonstrasikan hal di atas, saya membuat direktori pengujian untuk kelas C.java dan 3 subdirektori untuk antarmuka di file I1.java dan I2.java. Direktori root untuk pengujian berisi kode sumber untuk kelas C.java. Direktori dasar berisi versi antarmuka yang cocok untuk eksekusi dan kompilasi: antarmuka I1 memiliki metode default m(); Antarmuka I2 belum memiliki metode apa pun. Kelas memiliki metodemain
sehingga kita dapat menjalankannya untuk mengujinya. Ia memeriksa apakah ada argumen baris perintah, sehingga kita dapat dengan mudah menjalankannya baik dengan atau tanpa memanggil m()
.
~/github/test$ cat C.java
public class C implements I1, I2 {
public static void main(String[] args) {
C c = new C();
if( args.length == 0 ){
c.m();
}
}
}
~/github/test$ cat base/I1.java
public interface I1 {
default void m(){
System.out.println("hello interface 1");
}
}
~/github/test$ cat base/I2.java
public interface I2 {
}
Anda dapat mengkompilasi dan menjalankan kelas dari baris perintah.
~/github/test$ javac -cp .:base C.java
~/github/test$ java -cp .:base C
hello interface 1
Direktori yang kompatibel berisi versi antarmuka I2 yang mendeklarasikan metode m() sebagai abstrak, dan juga, karena alasan teknis, salinan I1.java yang tidak dimodifikasi.
~/github/test$ cat compatible/I2.java
public interface I2 {
void m();
}
Himpunan seperti itu tidak dapat digunakan untuk mengkompilasi kelas C:
~/github/test$ javac -cp .:compatible C.java
C.java:1: error: C is not abstract and does not override abstract method m() in I2
public class C implements I1, I2 {
^
1 error
Pesan kesalahannya sangat akurat. Namun, kita memiliki C.class dari kompilasi sebelumnya dan, jika kita mengkompilasi antarmuka ke dalam direktori yang kompatibel, kita akan memiliki dua antarmuka yang masih dapat digunakan untuk menjalankan kelas:
~/github/test$ javac compatible/I*.java
~/github/test$ java -cp .:compatible C
hello interface 1
Direktori ketiga - wrong
- berisi versi I2, yang juga mendeklarasikan metode m()
:
~/github/test$ cat wrong/I2.java
public interface I2 {
default void m(){
System.out.println("hello interface 2");
}
}
Anda bahkan tidak perlu khawatir tentang kompilasi. Meskipun metode tersebut dideklarasikan dua kali, kelas tersebut tetap dapat digunakan dan dijalankan hingga metode m() dipanggil. Untuk inilah kita memerlukan argumen baris perintah:
~/github/test$ javac wrong/*.java
~/github/test$ java -cp .:wrong C
Exception in thread "main" java.lang.IncompatibleClassChangeError: Conflicting default methods: I1.m I2.m
at C.m(C.java)
at C.main(C.java:5)
~/github/test$ java -cp .:wrong C x
~/github/test$
GO TO FULL VERSION