Sejarah evolusi antarmuka di Jawa

gambar

Antarmuka di Jawa telah berkembang pesat selama bertahun-tahun. Mari kita lihat perubahan apa yang terjadi dalam proses pengembangannya.

Antarmuka asli


Antarmuka di Java 1.0 cukup sederhana dibandingkan dengan apa yang ada sekarang. Mereka hanya dapat berisi dua jenis elemen: konstanta dan metode abstrak publik.

Bidang Konstan


Antarmuka dapat berisi bidang, seperti kelas reguler, tetapi dengan beberapa perbedaan:

  • Bidang harus diinisialisasi.
  • Bidang dianggap final statis publik
  • Pengubah publik, statis dan final tidak perlu ditentukan secara eksplisit (mereka "diletakkan" secara default)

public interface MyInterface { int MY_CONSTANT = 9; } 

Meskipun ini tidak ditentukan secara eksplisit, bidang MY_CONSTANT dianggap sebagai konstanta akhir statis publik. Anda dapat menambahkan pengubah ini, tetapi ini tidak perlu.

Metode abstrak


Elemen terpenting dari sebuah antarmuka adalah metodenya. Metode antarmuka juga berbeda dari metode kelas biasa:

  • Metode tidak memiliki tubuh
  • Implementasi metode disediakan oleh kelas yang mengimplementasikan antarmuka ini.
  • Metode dianggap publik dan abstrak bahkan jika tidak ditentukan secara eksplisit.
  • Metode tidak bisa final, karena kombinasi pengubah abstrak dan final tidak diizinkan di Jawa

 public interface MyInterface { int doSomething(); String doSomethingCompletelyDifferent(); } 

Bersarang


Java 1.1 memperkenalkan konsep kelas yang dapat ditempatkan di dalam kelas lain. Kelas semacam itu terdiri dari dua jenis: statis dan non-statis. Antarmuka juga dapat berisi antarmuka dan kelas lainnya.

Bahkan jika ini tidak ditentukan secara eksplisit, antarmuka dan kelas tersebut dianggap publik dan statis.

 public interface MyInterface { class MyClass { //... } interface MyOtherInterface { //... } } 

Enumerasi dan Anotasi


Dua tipe lagi diperkenalkan di Java 5: Enumeration and Annotations. Mereka juga dapat ditempatkan di dalam antarmuka.

 public interface MyInterface { enum MyEnum { FOO, BAR; } @interface MyAnnotation { //... } } 

Jenis Generik


Java 5 memperkenalkan konsep generik, tipe generik. Singkatnya: generik memungkinkan Anda untuk menggunakan tipe generik alih-alih menentukan tipe tertentu. Dengan demikian, Anda dapat menulis kode yang berfungsi dengan sejumlah jenis berbeda tanpa mengorbankan keamanan dan tanpa memberikan implementasi yang terpisah untuk masing-masing jenis.

Dalam antarmuka yang dimulai pada Java 5, Anda dapat menentukan tipe generik dan kemudian menggunakannya sebagai jenis nilai balik metode atau sebagai tipe argumen ke metode.

Antarmuka Box berfungsi baik jika Anda menggunakannya untuk menyimpan objek seperti String, Integer, List, Shoe, atau lainnya.

 interface Box<T> { void insert(T item); } class ShoeBox implements Box<Shoe> { public void insert(Shoe item) { //... } } 

Metode statis


Dimulai dengan Java 8, Anda dapat memasukkan metode statis di antarmuka. Pendekatan ini telah mengubah cara antarmuka bekerja untuk kita. Mereka sekarang bekerja sangat berbeda dari cara mereka bekerja sebelum Java 8. Awalnya, semua metode di antarmuka abstrak. Ini berarti bahwa antarmuka hanya menyediakan tanda tangan, tetapi bukan implementasi. Implementasi diserahkan kepada kelas yang mengimplementasikan antarmuka Anda.

Saat menggunakan metode statis di antarmuka, Anda juga perlu menyediakan implementasi dari tubuh metode. Untuk menggunakan metode ini di antarmuka, cukup gunakan kata kunci statis. Metode statis dianggap publik secara default.

 public interface MyInterface { // This works static int foo() { return 0; } // This does not work, // static methods in interfaces need body static int bar(); } 

Warisan Metode Statis


Tidak seperti metode statis biasa, metode statis di antarmuka tidak diwariskan. Ini berarti bahwa jika Anda ingin memanggil metode seperti itu, Anda harus memanggilnya langsung dari antarmuka, dan bukan dari kelas yang mengimplementasikannya.

 MyInterface.staticMethod(); 

Perilaku ini sangat berguna untuk menghindari beberapa masalah warisan. Bayangkan Anda memiliki kelas yang mengimplementasikan dua antarmuka. Setiap antarmuka memiliki metode statis dengan nama dan tanda tangan yang sama. Yang mana yang harus digunakan terlebih dahulu?

Mengapa ini bermanfaat?


Bayangkan Anda memiliki antarmuka dan serangkaian metode pembantu yang bekerja dengan kelas yang mengimplementasikan antarmuka ini.

Secara tradisional, telah ada pendekatan untuk menggunakan kelas pendamping. Selain antarmuka, kelas utilitas dibuat dengan nama yang sangat mirip yang berisi metode statis milik antarmuka.

Anda dapat menemukan contoh menggunakan pendekatan ini secara langsung di JDK: antarmuka java.util.Collection dan kelas utilitas java.util.Collections yang menyertainya.

Dengan metode statis di antarmuka, pendekatan ini tidak lagi relevan, tidak diperlukan dan tidak disarankan. Sekarang Anda dapat memiliki semuanya di satu tempat.

Metode standar


Metode default mirip dengan metode statis karena Anda juga harus menyediakan badan untuknya. Untuk mendeklarasikan metode default, cukup gunakan kata kunci default.

 public interface MyInterface { default int doSomething() { return 0; } } 

Tidak seperti metode statis, metode secara default diwarisi oleh kelas yang mengimplementasikan antarmuka. Yang penting, kelas-kelas tersebut dapat mendefinisikan kembali perilaku mereka jika perlu.

Meski ada satu pengecualian. Antarmuka tidak dapat memiliki metode default dengan tanda tangan yang sama dengan metode toString, equals, dan hashCode dari kelas Object. Lihatlah jawaban Brian Goetz untuk memahami validitas solusi semacam itu: Izinkan metode default untuk mengganti metode Object.

Mengapa ini bermanfaat?


Gagasan menerapkan metode langsung di antarmuka sepertinya tidak sepenuhnya benar. Jadi mengapa fungsi ini pertama kali diperkenalkan?

Antarmuka memiliki satu masalah. Segera setelah Anda memberikan API Anda kepada orang lain, itu akan selamanya "membatu" (tidak dapat diubah tanpa rasa sakit).

Secara tradisional, Java menganggap kompatibilitas sangat serius. Metode default menyediakan cara untuk memperluas antarmuka yang ada dengan metode baru. Yang paling penting, metode default sudah menyediakan implementasi spesifik. Ini berarti bahwa kelas yang mengimplementasikan antarmuka Anda tidak perlu menerapkan metode baru. Tetapi, jika perlu, metode default dapat diganti kapan saja jika implementasinya tidak lagi sesuai. Jadi, singkatnya, Anda dapat memberikan fungsionalitas baru ke kelas yang ada yang mengimplementasikan antarmuka Anda, sambil mempertahankan kompatibilitas.

Konflik


Mari kita bayangkan bahwa kita memiliki kelas yang mengimplementasikan dua antarmuka. Antarmuka ini memiliki metode default dengan nama dan tanda tangan yang sama.

 interface A { default int doSomething() { return 0; } } interface B { default int doSomething() { return 42; } } class MyClass implements A, B { } 

Sekarang metode default yang sama dengan tanda tangan yang sama diwarisi dari dua antarmuka yang berbeda. Setiap antarmuka memiliki implementasi metode ini sendiri.

Jadi, bagaimana kelas kita tahu yang mana dari dua implementasi yang berbeda untuk digunakan?

Dia tidak akan tahu. Kode di atas akan menghasilkan kesalahan kompilasi. Jika Anda perlu membuatnya bekerja, maka Anda perlu mengganti metode yang bertentangan di kelas Anda.

 interface A { default int doSomething() { return 0; } } interface B { default int doSomething() { return 42; } } class MyClass implements A, B { // Without this the compilation fails @Override public int doSomething() { return 256; } } 

Metode pribadi


Dengan munculnya Java 8 dan pengenalan metode default dan metode statis, antarmuka sekarang memiliki kemampuan untuk mengandung tidak hanya tanda tangan metode, tetapi juga implementasinya. Saat menulis implementasi seperti itu, disarankan agar metode yang rumit dibagi menjadi yang lebih sederhana. Kode semacam itu lebih mudah digunakan kembali, dipelihara, dan dipahami.

Untuk tujuan ini, Anda akan menggunakan metode pribadi, karena mereka dapat berisi semua detail implementasi yang tidak boleh terlihat dan digunakan dari luar.

Sayangnya di Java 8, sebuah antarmuka tidak dapat berisi metode pribadi. Ini berarti Anda dapat menggunakan:

  1. Teknik tubuh yang panjang, rumit dan sulit dipahami.
  2. Metode pembantu yang merupakan bagian dari antarmuka. Ini melanggar prinsip enkapsulasi dan mencemari API publik dari kelas antarmuka dan implementasi.

Untungnya, mulai di Java 9, Anda dapat menggunakan metode pribadi di antarmuka . Mereka memiliki fitur-fitur berikut:

  • metode pribadi memiliki tubuh, mereka tidak abstrak
  • mereka bisa statis atau non-statis
  • mereka tidak diwarisi oleh kelas yang mengimplementasikan antarmuka dan antarmuka
  • mereka dapat memanggil metode antarmuka lainnya
  • metode pribadi dapat memanggil metode pribadi lainnya, abstrak, statis, atau standar
  • metode statis privat hanya dapat memanggil metode statis statis dan privat lainnya

 public interface MyInterface { private static int staticMethod() { return 42; } private int nonStaticMethod() { return 0; } } 

Urutan kronologis


Berikut ini adalah daftar perubahan menurut versi Java:

Java 1.1


Kelas Bersarang

Antarmuka Bersarang

Java 5


Jenis Generik

Transfer Tertutup

Anotasi bersarang

Java 8


Metode standar

Metode statis

Jawa 9


Metode pribadi

Source: https://habr.com/ru/post/id482498/


All Articles