Ang Java ay isang object-oriented na wika. Nangangahulugan ito na kailangan mong magsulat ng mga Java program gamit ang isang object-oriented na paradigm. At ang paradigm na ito ay nangangailangan ng paggamit ng mga bagay at klase sa iyong mga programa. Subukan nating gumamit ng mga halimbawa upang maunawaan kung ano ang mga klase at bagay, at kung paano ilapat ang mga pangunahing prinsipyo ng OOP (abstraction, inheritance, polymorphism at encapsulation) sa pagsasanay.
Ano ang isang bagay?
Ang mundong ating ginagalawan ay binubuo ng mga bagay. Sa pagtingin sa paligid, makikita natin na napapalibutan tayo ng mga bahay, puno, sasakyan, muwebles, pinggan, at computer. Ang lahat ng mga bagay na ito ay mga bagay, at bawat isa sa kanila ay may isang hanay ng mga tiyak na katangian, pag-uugali, at layunin. Nakasanayan na namin ang mga bagay, at palagi naming ginagamit ang mga ito para sa mga partikular na layunin. Halimbawa, kung kailangan nating pumasok sa trabaho, gumagamit tayo ng kotse. Kung gusto naming kumain, gumagamit kami ng mga pinggan. At kung gusto nating magpahinga, hahanap tayo ng komportableng sofa. Nasanay ang mga tao sa pag-iisip sa mga tuntunin ng mga bagay upang malutas ang mga problema sa pang-araw-araw na buhay. Ito ay isang dahilan kung bakit ginagamit ang mga bagay sa programming. Ang pamamaraang ito ay tinatawag na object-oriented programming. Magbigay tayo ng halimbawa. Isipin na nakabuo ka ng bagong telepono at gusto mong simulan ang mass production. Bilang developer ng telepono, alam mo kung para saan ito, kung paano ito gumagana, at kung ano ang mga bahagi nito (katawan, mikropono, speaker, mga wire, mga pindutan, atbp.). Higit pa, ikaw lang ang nakakaalam kung paano ikonekta ang mga bahaging ito. Ngunit hindi mo pinaplano na gawing personal ang mga telepono — mayroon kang isang buong pangkat ng mga manggagawa upang gawin ito. Upang maalis ang pangangailangan na paulit-ulit na ipaliwanag kung paano ikonekta ang mga bahagi ng telepono, at upang matiyak na ang lahat ng mga telepono ay ginawa sa parehong paraan, bago mo simulan ang paggawa ng mga ito, kailangan mong gumawa ng isang guhit na naglalarawan kung paano nakaayos ang telepono. Sa OOP, tinatawag naming klase ang naturang paglalarawan, pagguhit, diagram, o template. Ito ay bumubuo ng batayan ng paglikha ng mga bagay kapag tumatakbo ang programa. Ang klase ay isang paglalarawan ng mga bagay na may partikular na uri — tulad ng karaniwang template na binubuo ng mga field, pamamaraan at isang constructor. Ang isang bagay ay isang halimbawa ng isang klase.Abstraction
Pag-isipan natin ngayon kung paano tayo maaaring lumipat mula sa isang bagay sa totoong mundo patungo sa isang bagay sa isang programa. Gagamitin namin ang telepono bilang isang halimbawa. Ang paraan ng komunikasyon na ito ay may kasaysayan na umabot ng higit sa 100 taon. Ang modernong telepono ay isang mas kumplikadong aparato kaysa sa nauna nitong ika-19 na siglo. Kapag ginagamit ang telepono, hindi namin iniisip ang tungkol sa organisasyon nito at ang mga prosesong nagaganap sa loob nito. Ginagamit lang namin ang mga function na ibinigay ng mga developer ng telepono: mga button o touch screen para magpasok ng numero ng telepono at tumawag. Ang isa sa mga unang interface ng telepono ay isang crank na kailangang i-rotate para makatawag. Siyempre, hindi ito masyadong maginhawa. Ngunit natupad nito ang tungkulin nito nang walang kamali-mali. Kung ihahambing mo ang pinakamoderno at ang pinakaunang mga telepono, matutukoy mo kaagad ang mga function na pinakamahalaga para sa huling ika-19 na siglong device at para sa modernong smartphone. Ang mga ito ay ang kakayahang tumawag at ang kakayahang tumanggap ng mga tawag. Sa katunayan, ito ang dahilan kung bakit ang telepono ay isang telepono, at hindi iba pa. Ngayon lang inilapat ang isang prinsipyo ng OOP: tukuyin ang pinakamahalagang katangian at impormasyon ng isang bagay. Ang prinsipyong ito ay tinatawag na abstraction. Sa OOP, ang abstraction ay maaari ding tukuyin bilang isang paraan ng pagre-represent ng mga elemento ng isang real-world na gawain bilang mga object sa isang programa. Ang abstraction ay palaging nauugnay sa generalization ng ilang mga katangian ng isang bagay, kaya ang pangunahing bagay ay ang paghiwalayin ang makabuluhang impormasyon mula sa hindi gaanong mahalaga sa konteksto ng gawaing nasa kamay. Bilang karagdagan, maaaring mayroong ilang mga antas ng abstraction. Hayaan na Subukan nating ilapat ang prinsipyo ng abstraction sa aming mga telepono. Upang magsimula, tutukuyin namin ang mga pinakakaraniwang uri ng mga telepono — mula sa pinakaunang mga telepono hanggang sa mga kasalukuyang telepono. Halimbawa, maaari nating katawanin ang mga ito sa anyo ng diagram sa Figure 1. Gamit ang abstraction, matutukoy na natin ngayon ang pangkalahatang impormasyon sa hierarchy ng object na ito: ang pangkalahatang abstract na object (telepono), mga karaniwang katangian ng telepono (hal. taon ng paglikha nito), at ang karaniwang interface (lahat ng mga telepono ay maaaring tumanggap at tumawag). Narito ang hitsura nito sa Java:
public abstract class AbstractPhone {
private int year;
public AbstractPhone(int year) {
this.year = year;
}
public abstract void call(int outgoingNumber);
public abstract void ring(int incomingNumber);
}
Sa isang programa, maaari kaming lumikha ng mga bagong uri ng mga telepono gamit ang abstract na klase na ito at paglalapat ng iba pang mga pangunahing prinsipyo ng OOP, na aming tuklasin sa ibaba.
Encapsulation
Sa abstraction, tinutukoy namin kung ano ang karaniwan para sa lahat ng mga bagay. Ngunit ang bawat uri ng telepono ay natatangi, kahit papaano ay naiiba sa iba. Sa isang programa, paano tayo gumuhit ng mga hangganan at makikilala ang indibidwalidad na ito? Paano natin ito gagawin upang walang sinuman ang maaaring aksidenteng o sadyang masira ang ating telepono o subukang i-convert ang isang modelo sa isa pa? Sa totoong mundo, ang sagot ay halata: kailangan mong ilagay ang lahat ng mga bahagi sa isang case ng telepono. Pagkatapos ng lahat, kung hindi mo — sa halip na iwan ang lahat ng panloob na bahagi ng telepono at mga wire sa pagkonekta sa labas — tiyak na gustong "pahusayin" ng ilang mausisa na eksperimento ang aming telepono. Upang maiwasan ang gayong pag-uukit, ang prinsipyo ng encapsulation ay ginagamit sa disenyo at operasyon ng isang bagay. Ang prinsipyong ito ay nagsasaad na ang mga katangian at pag-uugali ng isang bagay ay pinagsama sa isang klase, ang object' Ang panloob na pagpapatupad ay nakatago mula sa gumagamit, at isang pampublikong interface ay ibinigay para sa pagtatrabaho sa bagay. Ang gawain ng programmer ay tukuyin kung alin sa mga katangian at pamamaraan ng isang bagay ang dapat na magagamit para sa pampublikong pag-access, at kung alin ang mga panloob na detalye ng pagpapatupad na hindi dapat ma-access.Encapsulation at access control
Ipagpalagay na ang impormasyon tungkol sa isang telepono (taon ng produksyon nito o logo ng gumawa) ay nakaukit sa likod nito kapag ginawa ito. Ang impormasyon (estado nito) ay tiyak sa partikular na modelong ito. Masasabi nating tiniyak ng tagagawa na ang impormasyong ito ay hindi nababago — malabong maisip ng sinuman na tanggalin ang ukit. Sa mundo ng Java, inilalarawan ng isang klase ang estado ng mga bagay sa hinaharap gamit ang mga patlang, at ang kanilang pag-uugali ay inilalarawan gamit ang mga pamamaraan. Ang pag-access sa estado at gawi ng isang bagay ay kinokontrol gamit ang mga modifier na inilapat sa mga field at pamamaraan: pribado, protektado, pampubliko, at default. Halimbawa, napagpasyahan namin na ang taon ng produksyon, pangalan ng tagagawa, at isa sa mga pamamaraan ay mga panloob na detalye ng pagpapatupad ng klase at hindi maaaring baguhin ng iba pang mga bagay sa programa. Sa code,
public class SomePhone {
private int year;
private String company;
public SomePhone(int year, String company) {
this.year = year;
this.company = company;
}
private void openConnection(){
// findSwitch
// openNewConnection...
}
public void call() {
openConnection();
System.out.println("Calling");
}
public void ring() {
System.out.println("Ring-ring");
}
}
Ang pribadong modifier ay nagpapahintulot sa mga field at pamamaraan ng klase na ma-access lamang sa loob ng klase na ito. Nangangahulugan ito na imposibleng ma-access ang mga pribadong patlang mula sa labas, dahil ang mga pribadong pamamaraan ay hindi matatawag. Ang paghihigpit sa pag-access sa paraan ng openConnection ay nag-iiwan din sa amin ng kakayahang malayang baguhin ang panloob na pagpapatupad ng pamamaraan, dahil ang pamamaraan ay garantisadong hindi gagamitin o matakpan ang gawain ng iba pang mga bagay. Upang gumana sa aming bagay, iniiwan namin ang mga pamamaraan ng tawag at pag-ring na magagamit gamit ang pampublikong modifier. Ang pagbibigay ng mga pampublikong pamamaraan para sa pagtatrabaho sa mga bagay ay bahagi din ng encapsulation, dahil kung ang pag-access ay ganap na tinanggihan, ito ay magiging walang silbi.
Mana
Tingnan natin muli ang diagram ng mga telepono. Maaari mong makita na ito ay isang hierarchy kung saan ang isang modelo ay may lahat ng mga tampok ng mga modelo na matatagpuan mas mataas sa kahabaan ng sangay nito, at nagdaragdag ng ilan sa sarili nito. Halimbawa, ang isang smartphone ay gumagamit ng isang cellular network para sa komunikasyon (may mga katangian ng isang cell phone), ay wireless at portable (may mga katangian ng isang cordless phone), at maaaring tumanggap at tumawag (may mga katangian ng isang telepono). Ang mayroon tayo dito ay pamana ng mga katangian ng bagay. Sa programming, ang ibig sabihin ng inheritance ay ang paggamit ng mga kasalukuyang klase upang tukuyin ang mga bago. Isaalang-alang natin ang isang halimbawa ng paggamit ng mana upang lumikha ng isang klase ng smartphone. Ang lahat ng cordless phone ay pinapagana ng mga rechargeable na baterya, na may partikular na tagal ng baterya. Alinsunod dito, idinaragdag namin ang property na ito sa klase ng cordless phone:
public abstract class CordlessPhone extends AbstractPhone {
private int hour;
public CordlessPhone (int year, int hour) {
super(year);
this.hour = hour;
}
}
Ang mga cell phone ay nagmamana ng mga katangian ng isang cordless na telepono, at ipinapatupad namin ang mga paraan ng pagtawag at pag-ring sa klase na ito:
public class CellPhone extends CordlessPhone {
public CellPhone(int year, int hour) {
super(year, hour);
}
@Override
public void call(int outgoingNumber) {
System.out.println("Calling " + outgoingNumber);
}
@Override
public void ring(int incomingNumber) {
System.out.println("Incoming call from " + incomingNumber);
}
}
At sa wakas, mayroon kaming klase ng smartphone, na, hindi tulad ng mga klasikong cell phone, ay may ganap na operating system. Maaari mong palawakin ang functionality ng iyong smartphone sa pamamagitan ng pagdaragdag ng mga bagong program na maaaring tumakbo sa operating system nito. Sa code, ang klase ay maaaring ilarawan tulad ng sumusunod:
public class Smartphone extends CellPhone {
private String operationSystem;
public Smartphone(int year, int hour, String operationSystem) {
super(year, hour);
this.operationSystem = operationSystem;
}
public void install(String program) {
System.out.println("Installing " + program + " for " + operationSystem);
}
}
Gaya ng nakikita mo, gumawa kami ng medyo bagong code para ilarawan ang klase ng Smartphone , ngunit nakakuha kami ng bagong klase na may bagong functionality. Ang prinsipyong ito ng OOP ay ginagawang posible na makabuluhang bawasan ang halaga ng Java code na kinakailangan, kaya ginagawang mas madali ang buhay para sa programmer.
Polymorphism
Sa kabila ng mga pagkakaiba sa hitsura at disenyo ng iba't ibang uri ng mga telepono, matutukoy natin ang ilang karaniwang pag-uugali: lahat sila ay maaaring tumanggap at tumawag at lahat ay may medyo malinaw at simpleng hanay ng mga kontrol. Sa mga tuntunin ng programming, ang prinsipyo ng abstraction (na pamilyar na tayo) ay nagbibigay-daan sa amin na sabihin na ang mga bagay sa telepono ay may isang karaniwang interface. Iyon ang dahilan kung bakit ang mga tao ay madaling gumamit ng iba't ibang modelo ng mga telepono na may parehong mga kontrol (mga mekanikal na pindutan o isang touchscreen), nang hindi sinisiyasat ang mga teknikal na detalye ng device. Kaya, palagi kang gumagamit ng cell phone at madali kang makatawag mula sa landline ng iyong kaibigan. Ang prinsipyo ng OOP na nagsasabing ang isang programa ay maaaring gumamit ng mga bagay na may karaniwang interface nang walang anumang impormasyon tungkol sa panloob na istraktura ng bagay ay tinatawag na polymorphism. Hayaan na Isipin na kailangan namin ang aming programa upang ilarawan ang isang user na maaaring gumamit ng anumang telepono upang tumawag sa isa pang user. Narito kung paano natin ito magagawa:
public class User {
private String name;
public User(String name) {
this.name = name;
}
public void callAnotherUser(int number, AbstractPhone phone){
// And here's polymorphism: using the AbstractPhone type in the code!
phone.call(number);
}
}
}
Ngayon ay ilalarawan namin ang ilang uri ng mga telepono. Isa sa mga unang telepono:
public class ThomasEdisonPhone extends AbstractPhone {
public ThomasEdisonPhone(int year) {
super(year);
}
@Override
public void call(int outgoingNumber) {
System.out.println("Crank the handle");
System.out.println("What number would you like to connect to?");
}
@Override
public void ring(int incomingNumber) {
System.out.println("The phone is ringing");
}
}
Isang ordinaryong landline na telepono:
public class Phone extends AbstractPhone {
public Phone(int year) {
super(year);
}
@Override
public void call(int outgoingNumber) {
System.out.println("Calling " + outgoingNumber);
}
@Override
public void ring(int incomingNumber) {
System.out.println("The phone is ringing");
}
}
At sa wakas, isang cool na video phone:
public class VideoPhone extends AbstractPhone {
public VideoPhone(int year) {
super(year);
}
@Override
public void call(int outgoingNumber) {
System.out.println("Connecting video call to " + outgoingNumber);
}
@Override
public void ring(int incomingNumber) {
System.out.println("Incoming video call from " + incomingNumber);
}
}
Gagawa kami ng mga bagay sa pangunahing() na pamamaraan at subukan ang callAnotherUser() na pamamaraan:
AbstractPhone firstPhone = new ThomasEdisonPhone(1879);
AbstractPhone phone = new Phone(1984);
AbstractPhone videoPhone=new VideoPhone(2018);
User user = new User("Jason");
user.callAnotherUser(224466, firstPhone);
// Crank the handle
// What number would you like to connect to?
user.callAnotherUser(224466, phone);
// Calling 224466
user.callAnotherUser(224466, videoPhone);
// Connecting video call to 224466
Ang pagtawag sa parehong paraan sa object ng gumagamit ay gumagawa ng iba't ibang mga resulta. Ang isang partikular na pagpapatupad ng paraan ng tawag ay pinili nang dynamic sa loob ng callAnotherUser() na paraan batay sa partikular na uri ng bagay na ipinasa kapag tumatakbo ang programa. Ito ang pangunahing bentahe ng polymorphism – ang kakayahang pumili ng pagpapatupad sa runtime. Sa mga halimbawa ng mga klase ng telepono na ibinigay sa itaas, ginamit namin ang overriding ng pamamaraan — isang trick kung saan binabago namin ang pagpapatupad ng isang pamamaraan na tinukoy sa base class nang hindi binabago ang signature ng pamamaraan. Ito ay mahalagang pinapalitan ang pamamaraan: ang bagong pamamaraan na tinukoy sa subclass ay tinatawag kapag ang programa ay naisakatuparan. Kadalasan, kapag na-override namin ang isang paraan, ang @Overrideginagamit ang anotasyon. Sinasabi nito sa compiler na suriin ang mga lagda ng mga overridden at overriding na pamamaraan. Panghuli, upang matiyak na ang iyong mga programa sa Java ay naaayon sa mga prinsipyo ng OOP, sundin ang mga tip na ito:
- tukuyin ang mga pangunahing katangian ng isang bagay;
- tukuyin ang mga karaniwang katangian at pag-uugali at gumamit ng mana kapag lumilikha ng mga klase;
- gumamit ng mga abstract na uri upang ilarawan ang mga bagay;
- subukang palaging itago ang mga pamamaraan at field na nauugnay sa panloob na pagpapatupad ng isang klase.
GO TO FULL VERSION