Razgovor o Java enkapsulaciji: osnovni koncept objektno orijentisanog programiranja u Javi
U ovoj sekciji ćemo govoriti o Java enkapsulaciji, koja se ubraja u tri glavne odlike Jave; kada je razjasnimo, to će značajno pomoći kasnijem programiranju.
Enkapsulacija, shvaćena doslovno, znači pakovanje; stručnije rečeno — informaciono skrivanje, odnosno korišćenjem apstrakcije se podaci i operacije nad tim podacima obuhvataju zajedno, čime se oblikuje nedeljiva samostalna celina.
Podaci su zaštićeni unutar klase, pri čemu se koliko god mogu prikrivaju interni detalji implementacije, a ostavljaju se samo određeni spoljni interfejsi preko kojih klasa komunicira sa okolinom.
Drugi objekti mogu da sarađuju sa ovim enkapsuliranim objektom samo preko ovlašćenih operacija. Drugim rečima, korisnik ne mora (i ne može) da zna interne detalje objekta, ali može da mu pristupa preko interfejsa koje objekat nudi.
Enkapsulacija donosi četiri velike koristi:
- Dobra enkapsulacija može da smanji spregnutost (coupling).
- Interna struktura klase se može slobodno menjati.
- Moguća je preciznija kontrola nad članovima.
- Sakrivaju se informacije i detalji implementacije.
Za početak pogledajmo dve klase.
Husband.java
public class Husband {
/*
* Enkapsulacija polja
* Ime, pol, uzrast i supruga osobe su privatna svojstva te osobe
*/
private String name ;
private String sex ;
private int age ;
private Wife wife;
/*
* setter() i getter() su interfejsi koje ovaj objekat nudi spolja
*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setWife(Wife wife) {
this.wife = wife;
}
}Wife.java
public class Wife {
private String name;
private int age;
private String sex;
private Husband husband;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public void setAge(int age) {
this.age = age;
}
public void setHusband(Husband husband) {
this.husband = husband;
}
public Husband getHusband() {
return husband;
}
}Može se videti da polje wife unutar klase Husband nema getter(), a isto tako polje age klase Wife nema metodu getter(). Razlog mislim da vam je jasan.
Nijedna žena ne želi da neko zna njene godine.
Enkapsulacija dakle privatizuje polja objekta, a istovremeno obezbeđuje metode kojima spoljašnjost može da pristupa tim poljima. Ako ne želimo da spoljašnjost pristupa nekom polju, jednostavno ne moramo da obezbedimo metodu za pristup.
Međutim, ako klasa spoljašnjosti ne pruži nijedan način pristupa, onda ta klasa i nema nekog značaja.
Na primer, posmatrajmo kuću kao objekat — unutra je lepa dekoracija, kauč, televizor, klima, sto za čaj i slično, i to su privatna svojstva te kuće. Ali ako ne bismo imali one zidove koji zaklanjaju pogled, da li bi sve bilo na uvid? Bez trunke privatnosti!
Zahvaljujući tom zaklanjajućem zidu možemo imati svoju privatnost i proizvoljno menjati unutrašnji raspored bez uticaja na ljude napolju.
Ali bez vrata i prozora, kutija čvrsto umotana u crnu foliju i nema nekog smisla; zato kroz vrata i prozore i drugi mogu videti unutrašnji pejzaž. Može se reći da su vrata i prozori interfejsi koje objekat kuće ostavlja spoljašnjosti za pristup.
Ovim još uvek ne možemo da osetimo prave koristi enkapsulacije. Sada ćemo iz ugla programa da analiziramo šta enkapsulacija donosi. Da ne koristimo enkapsulaciju, objekat ne bi imao setter() i getter(), pa bi klasa Husband izgledala ovako:
public class Husband {
public String name ;
public String sex ;
public int age ;
public Wife wife;
}Koristili bismo je ovako:
Husband husband = new Husband();
husband.age = 30;
husband.name = "Zhang San";
husband.sex = "muski"; // deluje pomalo suvišnoAli šta ako jednog dana poželimo da promenimo klasu Husband, na primer da age pretvorimo u tip String? Ako ste klasu koristili samo na jednom mestu, još u redu, ali ako imate desetine ili stotine takvih mesta, da li biste popadali od prepravki? Uz enkapsulaciju ne moramo ništa da menjamo — dovoljno je da malo izmenimo metodu setAge() klase Husband.
public class Husband {
/*
* Enkapsulacija polja
* Ime, pol, uzrast i supruga osobe su privatna svojstva te osobe
*/
private String name ;
private String sex ;
private String age ; /* pretvoreno u tip String */
private Wife wife;
public String getAge() {
return age;
}
public void setAge(int age) {
// samo izvrši pretvaranje
this.age = String.valueOf(age);
}
/** ostale setter/getter metode su izostavljene **/
}Svi ostali delovi koda i dalje pozivaju (husband.setAge(22)) bez promene.
Ovde se zaista vidi da enkapsulacija omogućava lakše menjanje interne implementacije klase, bez potrebe za izmenom koda koji tu klasu koristi.
Pogledajmo još jednu korist: enkapsulacija omogućava precizniju kontrolu nad poljima.
Opet klasa Husband — pri radu sa ovim objektom obično ne grešimo, ali ponekad ste odsutni pa napišete sledeće:
Husband husband = new Husband();
husband.age = 300;Možda je to ispalo nenamerno; ako primetite, još u redu, ali ako ne primetite — nevolja je velika, ko je video 300-godišnjeg starog demona!
Međutim, uz enkapsulaciju možemo izbeći taj problem. Uradimo određenu kontrolu nad ulazom za pristup polju age (kroz setter), na primer:
public class Husband {
/*
* Enkapsulacija polja
* Ime, pol, uzrast i supruga osobe su privatna svojstva te osobe
*/
private String name ;
private String sex ;
private int age ; /* pretvoreno u tip String */
private Wife wife;
public int getAge() {
return age;
}
public void setAge(int age) {
if(age > 120){
System.out.println("ERROR:error age input...."); // poruka o grešci
}else{
this.age = age;
}
}
/** ostale setter/getter metode su izostavljene **/
}Gore su primeri kontrole nad setter metodom, ali preko enkapsulacije možemo dobro kontrolisati i izlaz objekta. Na primer, pol se u bazi obično čuva kao 1 ili 0, ali na korisničkom prikazu ne možemo prikazivati 1 ili 0; dovoljno je da u metodi getter() uradimo odgovarajuću konverziju.
public String getSexName() {
if("0".equals(sex)){
sexName = "zenski";
}
else if("1".equals(sex)){
sexName = "muski";
}
return sexName;
}Pri upotrebi dovoljno je da koristimo sexName i prikaz pola biće ispravan. Ista logika važi i za različite akcije na osnovu različitih statusa.
public String getCzHTML(){
if("1".equals(zt)){
czHTML = "<a href='javascript:void(0)' onclick='qy("+id+")'>Aktiviraj</a>";
}
else{
czHTML = "<a href='javascript:void(0)' onclick='jy("+id+")'>Deaktiviraj</a>";
}
return czHTML;
}Referentni link: https://www.cnblogs.com/chenssy/p/3351835.html, obradio: Erge
