JavaRush /Java Blog /Random-ID /Metode Default di Java 8: Apa yang Bisa dan Tidak Bisa Di...
Spitfire
Level 33

Metode Default di Java 8: Apa yang Bisa dan Tidak Bisa Dilakukan?

Dipublikasikan di grup Random-ID
Terjemahan artikel yang ditulis oleh Peter Verhas tertanggal April 2014. Metode Default di Java 8: Apa yang Bisa dan Tidak Bisa Dilakukan?  - 1Dari 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.
Metode Default di Java 8: Apa yang Bisa dan Tidak Bisa Dilakukan?  - 2Dalam hal ini kelas berfungsi. Anda tidak dapat mengkompilasinya dengan antarmuka yang diperbarui, tetapi ini dikompilasi dengan versi yang lebih lama dan karenanya berfungsi. Sekarang
  • ubah antarmuka dengan metode m() abstrak dan tambahkan implementasi default.
  • Kompilasi antarmuka yang dimodifikasi.
  • Jalankan kelas: kesalahan.
Ketika ada dua antarmuka yang menyediakan implementasi default suatu metode, metode tersebut tidak dapat dipanggil dalam suatu kelas kecuali metode tersebut diimplementasikan oleh kelas itu sendiri (sekali lagi, baik sendiri atau diwarisi dari kelas lain). Metode Default di Java 8: Apa yang Bisa dan Tidak Bisa Dilakukan?  - 3Kompatibel dengan kelas. Itu dapat dimuat dengan antarmuka yang dimodifikasi. Bahkan mungkin berjalan sampai suatu metode dipanggil yang memiliki implementasi default di kedua antarmuka.

Kode contoh

Metode Default di Java 8: Apa yang Bisa dan Tidak Bisa Dilakukan?  - 4Untuk 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 metode mainsehingga 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$

Kesimpulan

Saat Anda mem-porting perpustakaan Anda ke Java 8 dan mengubah antarmuka untuk menyertakan metode default, Anda mungkin tidak akan mengalami masalah apa pun. Setidaknya, itulah yang diharapkan oleh pengembang perpustakaan Java 8 saat mereka menambahkan fungsionalitas. Aplikasi yang menggunakan perpustakaan Anda masih menggunakannya untuk Java 7, di mana tidak ada metode default. Jika beberapa perpustakaan digunakan secara bersamaan, ada kemungkinan konflik. Bagaimana cara menghindarinya? Rancang API perpustakaan Anda dengan cara yang sama seperti sebelumnya. Jangan berpuas diri dengan mengandalkan kemampuan metode default. Itu adalah pilihan terakhir. Pilih nama dengan hati-hati untuk menghindari tabrakan dengan antarmuka lain. Mari kita lihat bagaimana perkembangan Java yang menggunakan fitur ini.
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION