hello! Hari ini kita akan bercakap tentang konsep penting dalam Java - antara muka. Perkataan itu mungkin biasa kepada anda. Sebagai contoh, kebanyakan program komputer dan permainan mempunyai antara muka. Dalam erti kata yang luas, antara muka ialah sejenis "kawalan jauh" yang menghubungkan dua pihak yang berinteraksi antara satu sama lain. Contoh mudah antara muka daripada kehidupan seharian ialah alat kawalan jauh TV. Ia menghubungkan dua objek, seseorang dan TV, dan melaksanakan tugas yang berbeza: naikkan atau turunkan kelantangan, tukar saluran, hidupkan atau matikan TV. Satu pihak (orang itu) perlu mengakses antara muka (tekan butang kawalan jauh) untuk pihak lain melakukan tindakan. Contohnya, untuk TV menukar saluran ke saluran seterusnya. Dalam kes ini, pengguna tidak perlu mengetahui peranti TV dan bagaimana proses menukar saluran dilaksanakan di dalamnya. Semua pengguna mempunyai akses kepada antara muka . Tugas utama adalah untuk mendapatkan hasil yang diinginkan. Apakah kaitan ini dengan pengaturcaraan dan Java? Terus :) Mencipta antara muka adalah sangat serupa dengan mencipta kelas biasa, tetapi bukannya perkataan
class
kami menentukan perkataan interface
. Mari lihat antara muka Java yang paling mudah dan cari cara ia berfungsi dan untuk apa ia diperlukan:
public interface Swimmable {
public void swim();
}
Kami mencipta antara muka Swimmable
yang boleh berenang . Ini adalah sesuatu seperti alat kawalan jauh kami, yang mempunyai satu "butang": kaedahnya swim()
ialah "berenang". Bagaimanakah kita boleh menggunakan " kawalan jauh " ini? Untuk tujuan ini kaedah, i.e. butang pada alat kawalan jauh kami perlu dilaksanakan. Untuk menggunakan antara muka, kaedahnya mesti dilaksanakan oleh beberapa kelas program kami. Mari kita buat kelas yang objeknya sesuai dengan penerangan "boleh berenang." Sebagai contoh, kelas itik sesuai Duck
:
public class Duck implements Swimmable {
public void swim() {
System.out.println("Duck, swim!");
}
public static void main(String[] args) {
Duck duck = new Duck();
duck.swim();
}
}
Apa yang kita lihat di sini? Kelas Duck
dikaitkan dengan antara muka Swimmable
menggunakan kata kunci implements
. Jika anda masih ingat, kami menggunakan mekanisme yang sama untuk menyambungkan dua kelas dalam warisan, hanya terdapat perkataan " extends ". " public class Duck implements Swimmable
" boleh diterjemahkan secara literal untuk kejelasan: "kelas awam Duck
melaksanakan antara muka Swimmable
." Ini bermakna kelas yang dikaitkan dengan antara muka mesti melaksanakan semua kaedahnya. Sila ambil perhatian: dalam kelas kami, Duck
sama seperti dalam antara muka , Swimmable
terdapat kaedah swim()
, dan di dalamnya terdapat beberapa jenis logik. Ini adalah keperluan wajib. Jika kita hanya menulis " public class Duck implements Swimmable
" dan tidak mencipta kaedah swim()
dalam kelas Duck
, pengkompil akan memberi kita ralat: Duck bukan abstrak dan tidak mengatasi kaedah abstrak swim() dalam Swimmable Mengapa ini berlaku? Jika kami menerangkan ralat menggunakan contoh TV, ternyata kami memberi seseorang kawalan jauh dengan butang "tukar saluran" dari TV yang tidak tahu cara menukar saluran. Pada ketika ini, tekan butang seberapa banyak yang anda suka, tiada apa yang akan berfungsi. Alat kawalan jauh itu sendiri tidak menukar saluran: ia hanya memberikan isyarat kepada TV, di dalamnya proses kompleks menukar saluran dilaksanakan. Begitu juga dengan itik kami: ia mesti boleh berenang supaya ia boleh diakses menggunakan antara muka Swimmable
. Jika dia tidak tahu bagaimana untuk melakukan ini, antara muka Swimmable
tidak akan menghubungkan kedua-dua pihak - orang dan program. Seseorang tidak akan dapat menggunakan kaedah swim()
untuk membuat objek Duck
di dalam program terapung. Kini anda telah melihat dengan lebih jelas untuk kegunaan antara muka. Antara muka menerangkan tingkah laku yang kelas yang melaksanakan antara muka mesti ada. "Tingkah laku" ialah koleksi kaedah. Jika kita ingin mencipta berbilang messenger, cara paling mudah untuk melakukannya ialah dengan mencipta antara muka Messenger
. Apakah yang boleh dilakukan oleh mana-mana utusan? Dalam bentuk yang ringkas, terima dan hantar mesej.
public interface Messenger{
public void sendMessage();
public void getMessage();
}
Dan kini kita hanya boleh membuat kelas messenger kita dengan melaksanakan antara muka ini. Pengkompil itu sendiri akan "memaksa" kami untuk melaksanakannya di dalam kelas. Telegram:
public class Telegram implements Messenger {
public void sendMessage() {
System.out.println("Sending a message to Telegram!");
}
public void getMessage() {
System.out.println("Reading the message in Telegram!");
}
}
WhatsApp:
public class WhatsApp implements Messenger {
public void sendMessage() {
System.out.println("Sending a WhatsApp message!");
}
public void getMessage() {
System.out.println("Reading a WhatsApp message!");
}
}
Viber:
public class Viber implements Messenger {
public void sendMessage() {
System.out.println("Sending a message to Viber!");
}
public void getMessage() {
System.out.println("Reading a message in Viber!");
}
}
Apakah faedah yang diberikan ini? Yang paling penting ialah gandingan longgar. Bayangkan bahawa kami sedang mereka bentuk program di mana kami akan mengumpul data pelanggan. Kelas Client
mesti mempunyai medan yang menunjukkan messenger yang digunakan oleh pelanggan. Tanpa antara muka ia akan kelihatan pelik:
public class Client {
private WhatsApp whatsApp;
private Telegram telegram;
private Viber viber;
}
Kami mencipta tiga medan, tetapi pelanggan boleh mempunyai hanya satu messenger dengan mudah. Cuma kita tak tahu yang mana satu. Dan agar tidak dibiarkan tanpa komunikasi dengan pelanggan, anda perlu "menolak" semua pilihan yang mungkin ke dalam kelas. Ternyata satu atau dua daripada mereka akan sentiasa berada di sana null
, dan mereka tidak diperlukan sama sekali untuk program ini berfungsi. Sebaliknya, lebih baik menggunakan antara muka kami:
public class Client {
private Messenger messenger;
}
Ini adalah contoh "gandingan longgar"! Daripada menentukan kelas messenger tertentu dalam class Client
, kami hanya menyebut bahawa klien mempunyai messenger. Yang mana satu akan ditentukan semasa program berlangsung. Tetapi mengapa kita memerlukan antara muka untuk ini? Mengapa mereka ditambahkan pada bahasa itu sama sekali? Soalannya bagus dan betul! Hasil yang sama boleh dicapai menggunakan warisan biasa, bukan? Kelas Messenger
ialah kelas induk, dan Viber
, Telegram
dan WhatsApp
merupakan pewaris. Memang boleh buat begitu. Tetapi ada satu tangkapan. Seperti yang anda sedia maklum, tiada warisan berbilang di Jawa. Tetapi terdapat pelbagai pelaksanaan antara muka. Kelas boleh melaksanakan seberapa banyak antara muka yang disukainya. Bayangkan kita mempunyai kelas Smartphone
yang mempunyai medan Application
- aplikasi yang dipasang pada telefon pintar.
public class Smartphone {
private Application application;
}
Aplikasi dan utusan adalah, tentu saja, serupa, tetapi mereka adalah perkara yang berbeza. Messenger boleh menjadi mudah alih dan desktop, manakala Aplikasi ialah aplikasi mudah alih. Jadi, jika kita menggunakan warisan, kita tidak akan dapat menambah objek Telegram
pada kelas Smartphone
. Lagipun, kelas Telegram
tidak boleh mewarisi daripada Application
dan daripada Messenger
! Dan kami telah berjaya mewarisinya daripada Messenger
, dan menambahnya pada kelas dalam borang ini Client
. Tetapi kelas Telegram
boleh dengan mudah melaksanakan kedua-dua antara muka! Oleh itu, dalam kelas Client
kita boleh melaksanakan objek Telegram
sebagai Messenger
, dan dalam kelas Smartphone
sebagai Application
. Begini caranya:
public class Telegram implements Application, Messenger {
//...methods
}
public class Client {
private Messenger messenger;
public Client() {
this.messenger = new Telegram();
}
}
public class Smartphone {
private Application application;
public Smartphone() {
this.application = new Telegram();
}
}
Sekarang kita boleh menggunakan kelas Telegram
sesuka hati. Di suatu tempat dia akan bertindak dalam peranan Application
, di suatu tempat dalam peranan Messenger
. Anda mungkin telah perasan bahawa kaedah dalam antara muka sentiasa "kosong", iaitu, ia tidak mempunyai pelaksanaan. Sebabnya adalah mudah: antara muka menerangkan tingkah laku, bukan melaksanakannya. "Semua objek kelas yang melaksanakan antara muka Swimmable
mesti boleh terapung": itu sahaja antara muka memberitahu kami. Bagaimana sebenarnya seekor ikan, itik atau kuda akan berenang terdapat soalan untuk kelas Fish
, Duck
dan Horse
, dan bukan untuk antara muka. Sama seperti menukar saluran adalah tugas TV. Alat kawalan jauh hanya memberi anda butang untuk melakukannya. Walau bagaimanapun, Java8 mempunyai penambahan yang menarik - kaedah lalai. Sebagai contoh, antara muka anda mempunyai 10 kaedah. 9 daripadanya dilaksanakan secara berbeza dalam kelas yang berbeza, tetapi satu dilaksanakan sama dalam semua. Sebelum ini, sebelum keluaran Java8, kaedah di dalam antara muka tidak mempunyai pelaksanaan sama sekali: pengkompil serta-merta melemparkan ralat. Sekarang anda boleh melakukannya seperti ini:
public interface Swimmable {
public default void swim() {
System.out.println("Swim!");
}
public void eat();
public void run();
}
Menggunakan kata kunci default
, kami telah mencipta kaedah dalam antara muka dengan pelaksanaan lalai. Kami perlu melaksanakan dua kaedah yang lain, eat()
dan run()
, kami sendiri dalam semua kelas yang akan melaksanakan Swimmable
. Tidak perlu melakukan ini dengan kaedah swim()
: pelaksanaannya akan sama dalam semua kelas. Ngomong-ngomong, anda telah menjumpai antara muka lebih daripada sekali dalam tugasan lepas, walaupun anda sendiri tidak menyedarinya :) Berikut ialah contoh yang jelas: Anda bekerja dengan antara muka List
dan Set
! Lebih tepat lagi, dengan pelaksanaannya - ArrayList
, LinkedList
, HashSet
dan lain-lain. Rajah yang sama menunjukkan contoh apabila satu kelas melaksanakan beberapa antara muka sekaligus. Sebagai contoh, LinkedList
ia melaksanakan antara muka List
dan Deque
(baris gilir dua belah). Anda juga biasa dengan antara muka Map
, atau sebaliknya, dengan pelaksanaannya - HashMap
. Dengan cara ini, dalam rajah ini anda boleh melihat satu ciri: antara muka boleh diwarisi antara satu sama lain. Antara muka SortedMap
diwarisi daripada Map
, dan Deque
diwarisi daripada baris gilir Queue
. Ini adalah perlu jika anda ingin menunjukkan sambungan antara antara muka, tetapi satu antara muka adalah versi lanjutan bagi yang lain. Mari kita lihat contoh dengan antara muka Queue
- baris gilir. Kami belum meneliti koleksinya lagi Queue
, tetapi ia agak ringkas dan tersusun seperti barisan biasa di kedai. Anda boleh menambah elemen hanya pada penghujung baris gilir, dan membawanya pergi dari awal sahaja. Pada peringkat tertentu, pembangun memerlukan versi gilir yang diperluaskan supaya elemen boleh ditambah dan diterima daripada kedua-dua belah pihak. Beginilah cara antara muka dicipta Deque
- baris gilir dua hala. Ia mengandungi semua kaedah baris gilir biasa, kerana ia adalah "induk" baris gilir dua hala, tetapi kaedah baharu telah ditambah.
GO TO FULL VERSION