1. Gambaran keseluruhan
Java 8 menghadirkan beberapa ciri baru, termasuk ekspresi lambda, antara muka fungsional, rujukan kaedah, aliran, Pilihan, dan kaedah statik dan lalai dalam antara muka.
Sebahagian daripada mereka telah dibahas dalam artikel ini. Walau bagaimanapun, kaedah statik dan lalai dalam antara muka memerlukan pandangan yang lebih mendalam sendiri.
Dalam artikel ini, kita akan membincangkan secara mendalam cara menggunakan kaedah statik dan lalai dalam antara muka dan melalui beberapa kes penggunaan di mana ia berguna.
2. Mengapa Kaedah Lalai dalam Antaramuka Diperlukan
Seperti kaedah antara muka biasa, kaedah lalai adalah secara tersirat umum - tidak perlu menentukan pengubah umum .
Tidak seperti kaedah antara muka biasa, mereka dinyatakan dengan kata kunci lalai di awal tandatangan kaedah , dan mereka memberikan pelaksanaan .
Mari lihat contoh ringkas:
public interface MyInterface { // regular interface methods default void defaultMethod() { // default method implementation } }
Sebab mengapa kaedah lalai dimasukkan dalam rilis Java 8 cukup jelas.
Dalam reka bentuk khas berdasarkan abstraksi, di mana antara muka mempunyai satu atau beberapa implementasi, jika satu atau lebih kaedah ditambahkan ke antara muka, semua pelaksanaan akan dipaksakan untuk menerapkannya juga. Jika tidak, reka bentuknya akan hancur.
Kaedah antara muka lalai adalah kaedah yang berkesan untuk menangani masalah ini. Mereka membolehkan kita menambahkan kaedah baru ke antara muka yang tersedia secara automatik dalam pelaksanaannya . Oleh itu, tidak perlu mengubah kelas pelaksana.
Dengan cara ini, keserasian ke belakang dipelihara dengan rapi tanpa perlu memfaktorkan semula pelaksana.
3. Kaedah Antaramuka Lalai dalam Tindakan
Untuk lebih memahami fungsi kaedah antara muka lalai , mari buat contoh mudah.
Katakan bahawa kita mempunyai antara muka Kenderaan yang naif dan hanya satu pelaksanaan. Mungkin ada lebih banyak lagi, tetapi mari kita mudahkan:
public interface Vehicle { String getBrand(); String speedUp(); String slowDown(); default String turnAlarmOn() { return "Turning the vehicle alarm on."; } default String turnAlarmOff() { return "Turning the vehicle alarm off."; } }
Dan mari tulis kelas pelaksana:
public class Car implements Vehicle { private String brand; // constructors/getters @Override public String getBrand() { return brand; } @Override public String speedUp() { return "The car is speeding up."; } @Override public String slowDown() { return "The car is slowing down."; } }
Terakhir, mari kita tentukan kelas utama khas , yang mencipta contoh Car dan memanggil kaedahnya:
public static void main(String[] args) { Vehicle car = new Car("BMW"); System.out.println(car.getBrand()); System.out.println(car.speedUp()); System.out.println(car.slowDown()); System.out.println(car.turnAlarmOn()); System.out.println(car.turnAlarmOff()); }
Perhatikan bagaimana kaedah lalai turnAlarmOn () dan turnAlarmOff () dari antara muka Kenderaan kami secara automatik tersedia di kelas Kereta .
Lebih jauh lagi, jika pada satu ketika kita memutuskan untuk menambahkan lebih banyak kaedah lalai ke antara muka Kenderaan , aplikasi akan tetap berfungsi, dan kita tidak perlu memaksa kelas untuk memberikan implementasi untuk kaedah baru.
Penggunaan kaedah lalai yang paling biasa dalam antaramuka adalah secara bertahap memberikan fungsi tambahan pada jenis tertentu tanpa merobohkan kelas pelaksana.
Di samping itu, mereka dapat digunakan untuk memberikan fungsi tambahan berdasarkan kaedah abstrak yang ada :
public interface Vehicle { // additional interface methods double getSpeed(); default double getSpeedInKMH(double speed) { // conversion } }
4. Peraturan Warisan Antaramuka Pelbagai
Kaedah antara muka lalai adalah ciri yang cukup bagus, tetapi dengan beberapa peringatan yang perlu disebutkan. Oleh kerana Java membenarkan kelas melaksanakan pelbagai antara muka, penting untuk mengetahui apa yang berlaku apabila kelas menerapkan beberapa antara muka yang menentukan kaedah lalai yang sama .
Untuk lebih memahami senario ini, mari kita tentukan antara muka Penggera baru dan refaktorkan kelas Kereta :
public interface Alarm { default String turnAlarmOn() { return "Turning the alarm on."; } default String turnAlarmOff() { return "Turning the alarm off."; } }
Dengan antaramuka baru ini menetapkan kaedah lalainya sendiri , kelas Kereta akan melaksanakan Kenderaan dan Penggera :
public class Car implements Vehicle, Alarm { // ... }
Dalam kes ini, kodnya tidak akan dikompilasi, kerana terdapat konflik yang disebabkan oleh pelbagai warisan antara muka (aka Masalah Berlian). The Car kelas akan mewarisi kedua-dua set lalai kaedah. Yang mana mesti dipanggil?
Untuk menyelesaikan kesamaran ini, kita mesti secara jelas memberikan pelaksanaan kaedah:
@Override public String turnAlarmOn() { // custom implementation } @Override public String turnAlarmOff() { // custom implementation }
Kami juga boleh meminta kelas kami menggunakan kaedah lalai salah satu antara muka .
Mari lihat contoh yang menggunakan kaedah lalai dari antara muka Kenderaan :
@Override public String turnAlarmOn() { return Vehicle.super.turnAlarmOn(); } @Override public String turnAlarmOff() { return Vehicle.super.turnAlarmOff(); }
Begitu juga, kita boleh meminta kelas menggunakan kaedah lalai yang ditentukan dalam antara muka Penggera :
@Override public String turnAlarmOn() { return Alarm.super.turnAlarmOn(); } @Override public String turnAlarmOff() { return Alarm.super.turnAlarmOff(); }
Tambahan pula, ia lebih mungkin untuk membuat kereta kelas menggunakan kedua-dua set kaedah lalai :
@Override public String turnAlarmOn() { return Vehicle.super.turnAlarmOn() + " " + Alarm.super.turnAlarmOn(); } @Override public String turnAlarmOff() { return Vehicle.super.turnAlarmOff() + " " + Alarm.super.turnAlarmOff(); }
5. Kaedah Antara Muka Statik
Selain dapat menyatakan kaedah lalai dalam antaramuka, Java 8 memungkinkan kita untuk menentukan dan menerapkan kaedah statik dalam antara muka .
Oleh kerana kaedah statik bukan milik objek tertentu, mereka bukan merupakan bagian dari API kelas yang melaksanakan antara muka, dan mereka harus dipanggil dengan menggunakan nama antara muka yang mendahului nama metode .
Untuk memahami bagaimana kaedah statik berfungsi di antara muka, mari kita ubah semula antara muka Kenderaan dan tambahkan padanya kaedah utiliti statik :
public interface Vehicle { // regular / default interface methods static int getHorsePower(int rpm, int torque) { return (rpm * torque) / 5252; } }
Mendefinisikan kaedah statik dalam antara muka adalah serupa dengan menentukan satu dalam kelas. Selain itu, kaedah statik boleh digunakan dalam kaedah statik dan lalai yang lain.
Sekarang, katakan bahawa kita ingin mengira kuasa kuda enjin kenderaan tertentu. Kami hanya memanggil kaedah getHorsePower () :
Vehicle.getHorsePower(2500, 480));
Idea di sebalik kaedah antara muka statik adalah menyediakan mekanisme mudah yang membolehkan kita meningkatkan tahap kohesi reka bentuk dengan menyatukan kaedah yang berkaitan di satu tempat tanpa perlu membuat objek.
Cukup banyak yang sama boleh dilakukan dengan kelas abstrak. Perbezaan utama terletak pada kenyataan bahawa kelas abstrak boleh mempunyai konstruktor, keadaan, dan tingkah laku .
Selanjutnya, kaedah statik dalam antaramuka memungkinkan untuk mengelompokkan kaedah utiliti yang berkaitan, tanpa harus membuat kelas utiliti buatan yang hanya menjadi tempat bagi kaedah statik.
6. Kesimpulannya
Dalam artikel ini, kami meneroka secara mendalam penggunaan kaedah antara muka statik dan lalai di Java 8. Pada pandangan pertama, ciri ini mungkin kelihatan sedikit ceroboh, terutama dari perspektif purist berorientasi objek. Sebaik-baiknya, antara muka tidak boleh merangkumi tingkah laku dan harus digunakan hanya untuk menentukan API awam dari jenis tertentu.
Untuk menjaga keserasian ke belakang dengan kod yang ada, kaedah statik dan lalai adalah pertukaran yang baik.
Seperti biasa, semua contoh kod yang ditunjukkan dalam artikel ini terdapat di GitHub.