Hi! Ngayon ay pag-uusapan natin ang isang mahalagang konsepto sa Java: mga interface. Ang salita ay malamang na pamilyar sa iyo. Halimbawa, karamihan sa mga computer program at laro ay may mga interface. Sa isang malawak na kahulugan, ang isang interface ay isang uri ng 'remote control' na nag-uugnay sa dalawang nakikipag-ugnayan na partido. Ang isang simpleng halimbawa ng isang interface sa pang-araw-araw na buhay ay isang TV remote control. Nag-uugnay ito ng dalawang bagay — isang tao at isang TV — at nagsasagawa ng iba't ibang gawain: lakasan o hinaan ang volume, lumipat ng channel, at i-on o i-off ang TV. Kailangang ma-access ng isang partido (ang tao) ang interface (pindutin ang isang pindutan sa remote control) upang maging sanhi ng pagkilos ng pangalawang partido. Halimbawa, upang gawing palitan ang TV sa susunod na channel. Higit pa rito, ang gumagamit ay hindi t kailangang malaman kung paano inayos ang TV o kung paano ipinapatupad ang proseso ng pagpapalit ng channel sa loob. Ang tanging bagay na may access ang user ay ang interface. Ang pangunahing layunin ay upang makuha ang ninanais na resulta. Ano ang kinalaman nito sa programming at Java? Lahat :) Ang paglikha ng isang interface ay halos kapareho sa paglikha ng isang regular na klase, ngunit sa halip ay gumagamit ng salitaklase , ipinapahiwatig namin ang salitang interface . Tingnan natin ang pinakasimpleng interface ng Java, tingnan kung paano ito gumagana, at kung bakit natin ito kakailanganin:
public interface CanSwim {
public void swim();
}
Gumawa kami ng interface ng CanSwim . Ito ay medyo katulad ng aming remote control, ngunit may isang 'button': ang swim() method. Ngunit paano natin gagamitin ang remote controller na ito? Para magawa ito, kailangan nating magpatupad ng paraan, ibig sabihin, ang ating remote control button. Upang gumamit ng isang interface, ang ilang mga klase sa aming programa ay dapat magpatupad ng mga pamamaraan nito. Mag-imbento tayo ng isang klase na ang mga bagay ay 'maaaring lumangoy'. Halimbawa, akma ang klase ng Duck :
public class Duck implements CanSwim {
public void swim() {
System.out.println("Duck, swim!");
}
public static void main(String[] args) {
Duck duck = new Duck();
duck.swim();
}
}
"Ano ang nakikita natin dito? Ang klase ng Duck ay 'nauugnay' sa interface ng CanSwim sa pamamagitan ng mga implement na keyword. Maaari mong maalala na gumamit kami ng katulad na mekanismo upang iugnay ang dalawang klase sa pamamagitan ng mana, ngunit sa kasong iyon ay ginamit namin ang salitang extend. Para sa kumpletong kalinawan, maaari naming isalin ang ' public class Duck implements CanSwim ' literal bilang: 'The public Duck class ay nagpapatupad ng CanSwim interface'. Nangangahulugan ito na ang isang klase na nauugnay sa isang interface ay dapat magpatupad ng lahat ng mga pamamaraan nito. Tandaan: ang aming Duck
klase, tulad ng ang CanSwim
interface, ay may swim()
pamamaraan, at naglalaman ito ng ilang lohika. Ito ay isang ipinag-uutos na kinakailangan. Kung isusulat lang natinpublic class Duck implements CanSwim
nang hindi gumagawa ng swim()
paraan sa Duck
klase, ang compiler ay magbibigay sa amin ng isang error: Duck ay hindi abstract at hindi override abstract method swim() sa CanSwim Bakit? Bakit ito nangyayari? Kung ipapaliwanag namin ang error gamit ang halimbawa sa TV, ito ay parang pagbibigay sa isang tao ng remote control ng TV na may button na 'palitan ang channel' na hindi makakapagpalit ng mga channel. Maaari mong pindutin ang pindutan hangga't gusto mo, ngunit hindi ito gagana. Ang remote control ay hindi nagbabago ng mga channel nang mag-isa: nagpapadala lamang ito ng signal sa TV, na nagpapatupad ng kumplikadong proseso ng pagpapalit ng channel. At gayon din ang aming pato: dapat itong marunong lumangoy upang ito ay matawag gamit ang CanSwim
interface. Kung hindi nito alam kung paano, angCanSwim
interface ay hindi nagkokonekta sa dalawang partido — ang tao at ang programa. Hindi magagamit ng tao ang swim()
paraan para lumangoy Duck
sa loob ng programa. Ngayon ay mas naiintindihan mo na kung para saan ang mga interface. Inilalarawan ng isang interface ang gawi na dapat mayroon ang mga klase na nagpapatupad ng interface. Ang 'Gawi' ay isang koleksyon ng mga pamamaraan. Kung gusto naming lumikha ng ilang messenger, ang pinakamadaling gawin ay ang paggawa ng Messenger
interface. Ano ang kailangan ng bawat mensahero? Sa pangunahing antas, dapat silang makatanggap at makapagpadala ng mga mensahe.
public interface Messenger{
public void sendMessage();
public void getMessage();
}
Ngayon ay maaari na lang nating gawin ang ating mga messenger class na nagpapatupad ng kaukulang interface. Ang compiler mismo ay 'puwersa' sa amin na ipatupad ang mga ito sa aming mga klase. Telegram:
public class Telegram implements Messenger {
public void sendMessage() {
System.out.println("Sending a Telegram message!");
}
public void getMessage() {
System.out.println("Receiving a Telegram message!");
}
}
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 Viber message!");
}
public void getMessage() {
System.out.println("Receiving a Viber message!");
}
}
Anong mga pakinabang ang ibinibigay nito? Ang pinakamahalaga sa kanila ay maluwag na pagkabit. Isipin na nagdidisenyo kami ng program na mangongolekta ng data ng kliyente. Tiyak na kailangan ng Client
klase ng field para ipahiwatig kung aling partikular na messenger ang ginagamit ng kliyente. Kung walang mga interface, magiging kakaiba ito:
public class Client {
private WhatsApp whatsApp;
private Telegram telegram;
private Viber viber;
}
Gumawa kami ng tatlong field, ngunit ang isang kliyente ay maaaring magkaroon lamang ng isang messenger. Hindi lang natin alam kung alin. Kaya kailangan nating idagdag ang bawat posibilidad sa klase upang makapag-usap sa kliyente. Lumalabas na ang isa o dalawa sa kanila ay palaging magiging null
, ganap na hindi kailangan ng programa. Mas mainam na gamitin ang aming interface sa halip:
public class Client {
private Messenger messenger;
}
Ito ay isang halimbawa ng maluwag na pagkabit! Sa halip na tukuyin ang isang partikular na klase ng messenger sa Client
klase, ipinapahiwatig lang namin na may messenger ang kliyente. Alin ang eksaktong matutukoy habang tumatakbo ang programa. Ngunit bakit kailangan natin ng mga interface para dito? Bakit idinagdag pa sila sa wika? Iyan ay isang magandang tanong — at ang tamang tanong! Hindi ba natin makakamit ang parehong resulta gamit ang ordinaryong mana? Ang Messenger
klase bilang magulang, at Viber
, Telegram
, at WhatsApp
bilang mga bata. Sa katunayan, ito ay posible. Ngunit may isang sagabal. Tulad ng alam mo na, ang Java ay walang multiple inheritance. Ngunit mayroong suporta para sa maramihang mga interface. Ang isang klase ay maaaring magpatupad ng maraming interface hangga't gusto mo. Isipin na mayroon kaming isang Smartphone
klase na may isaApp
field, na kumakatawan sa isang app na naka-install sa smartphone.
public class Smartphone {
private App app;
}
Siyempre, magkatulad ang app at messenger, ngunit magkaiba pa rin sila. Maaaring mayroong mga mobile at desktop na bersyon ng isang messenger, ngunit ang App ay partikular na kumakatawan sa isang mobile app. Narito ang deal — kung gumamit kami ng inheritance, hindi kami makakapagdagdag ng Telegram
object sa Smartphone
klase. Pagkatapos ng lahat, ang Telegram
klase ay hindi maaaring sabay na magmana App
at Messenger
! At ginawa na namin itong mana Messenger
at idinagdag sa Client
klase. Ngunit Telegram
madaling ipatupad ng klase ang parehong mga interface! Alinsunod dito, maaari nating bigyan ang Client
klase ng isang Telegram
bagay bilang isang Messenger
, at maaari nating ibigay ito sa Smartphone
klase bilang isang App
. Narito kung paano mo ito gagawin:
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();
}
}
Ngayon ginagamit namin ang Telegram
klase kung paano namin gusto. Sa ilang mga lugar, ito ay gumaganap bilang isang App
. Sa ibang mga lugar, ito ay gumaganap bilang isang Messenger
. Tiyak na napansin mo na ang mga pamamaraan ng interface ay palaging 'walang laman', ibig sabihin, wala silang pagpapatupad. Ang dahilan para dito ay simple: ang interface ay naglalarawan ng pag-uugali, ngunit hindi nito ipinapatupad ito. 'Ang lahat ng bagay na nagpapatupad ng CanSwim
interface ay dapat na marunong lumangoy': iyon lang ang sinasabi sa amin ng interface. Ang partikular na paraan ng paglangoy ng isda, itik, at kabayo ay isang tanong para sa Fish
, Duck
, atHorse
mga klase, hindi ang interface. Tulad ng pagpapalit ng channel ay isang gawain para sa TV. Ang remote ay nagbibigay lamang sa iyo ng isang pindutan para dito. Gayunpaman, lumitaw ang isang kawili-wiling karagdagan sa Java 8 — mga default na pamamaraan. Halimbawa, ang iyong interface ay may 10 pamamaraan. 9 sa mga ito ay may iba't ibang mga pagpapatupad sa iba't ibang mga klase, ngunit ang isa ay ipinatupad para sa lahat. Noong nakaraan, bago ang Java 8, ang mga pamamaraan ng interface ay walang anumang pagpapatupad: ang tagatala ay agad na nagbigay ng isang error. Ngayon ay maaari kang gumawa ng isang bagay tulad nito:
public interface CanSwim {
public default void swim() {
System.out.println("Swim!");
}
public void eat();
public void run();
}
Gamit ang default
keyword, nakagawa kami ng paraan ng interface na may default na pagpapatupad. Kailangan nating magbigay ng sarili nating pagpapatupad para sa dalawa pang pamamaraan — eat()
at run()
— sa lahat ng klase na nagpapatupad ng CanSwim
. Hindi namin kailangang gawin ito sa swim()
pamamaraan: ang pagpapatupad ay magiging pareho sa bawat klase. Oo nga pala, nakatagpo ka na ng mga interface sa mga nakaraang gawain, kahit na hindi mo napansin :) Narito ang isang matingkad na halimbawa: Nakipagtulungan ka sa List
at Set
mga interface! Mas tiyak, nagtrabaho ka sa kanilang mga pagpapatupad — ArrayList
, LinkedList
, HashSet
, atbp. Ang parehong diagram ay malinaw na nagbibigay ng halimbawa kung saan ang isang klase ay nagpapatupad ng maramihang mga interface sa parehong oras. Halimbawa, LinkedList
ipinapatupad ang List
atDeque
(double-ended queue) na mga interface. Pamilyar ka sa Map
interface, o sa halip, sa HashMap
pagpapatupad nito. Sa pamamagitan ng paraan, ang diagram na ito ay naglalarawan ng isang tampok: ang mga interface ay maaaring magmana ng iba pang mga interface. Ang SortedMap
interface ay nagmamana Map
, habang Deque
nagmamana Queue
. Ito ay kinakailangan kung gusto mong ipakita ang kaugnayan sa pagitan ng mga interface, kung saan ang isang interface ay isang pinahabang bersyon ng isa pa. Isaalang-alang natin ang isang halimbawa sa Queue
interface. Hindi pa kami nakakapag-reviewQueues
, ngunit ito ay medyo simple at gumagana tulad ng isang ordinaryong pila, o linya, sa isang tindahan. Maaari ka lamang magdagdag ng mga item sa dulo ng queue, at maaari lang kunin ang mga ito mula sa simula. Sa ilang mga punto, kailangan ng mga developer ng pinahusay na bersyon ng queue upang magdagdag at kumuha ng mga item sa magkabilang dulo. Kaya gumawa sila ng Deque
interface, na isang double-ended queue. Mayroon itong lahat ng mga pamamaraan ng isang ordinaryong pila. Pagkatapos ng lahat, ito ang magulang ng double-ended queue, ngunit nagdaragdag din ito ng mga bagong pamamaraan.
GO TO FULL VERSION