Kamusta! Sa mga nakaraang leksiyon, natutunan mo na kung paano ipahayag ang iyong sariling ganap na mga klase na may mga pamamaraan at field. Sa aralin ngayon, pag-uusapan natin ang tungkol sa mga Getters at Setters sa Java. Ito ay seryosong pag-unlad, magaling! Ngunit ngayon kailangan kong sabihin sa iyo ang isang hindi kasiya-siyang katotohanan. Hindi namin idineklara nang tama ang aming mga klase! Bakit? Sa unang tingin, ang sumusunod na klase ay walang anumang pagkakamali:
Ang mga pangalang ito ay nagmula sa "get" (ibig sabihin, "paraan para sa pagkuha ng halaga ng isang field") at "set" (ibig sabihin, "paraan para sa pagtatakda ng halaga ng isang field"). Tingnan natin kung ano ang hitsura ng mga ito sa aming klase ng Cat :
Sa halip, binibigyan ka ng tagagawa ng isang interface: ipinapasok lang ng user ang mga tamang digit, pinindot ang berdeng pindutan ng tawag, at magsisimula ang tawag. Wala siyang pakialam kung ano ang nangyayari sa loob ng mga circuit at wire, o kung paano nila ginagawa ang kanilang trabaho. Sa halimbawang ito, nililimitahan ng kumpanya ang pag-access sa "insides" (data) ng telepono at inilalantad lamang ang isang interface (mga pamamaraan). Bilang resulta, nakukuha ng user ang gusto niya (ang kakayahang tumawag) at tiyak na hindi masisira ang anumang bagay sa loob. Upang palakasin ang iyong natutunan, iminumungkahi naming manood ka ng isang video lesson mula sa aming Java Course
public class Cat {
public String name;
public int age;
public int weight;
public Cat(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
public Cat() {
}
public void sayMeow() {
System.out.println("Meow!");
}
}
Ngunit ginagawa nito. Isipin na nakaupo ka sa trabaho at isulat ang klase ng Cat na ito upang kumatawan sa mga pusa. At pagkatapos ay umuwi ka. Habang wala ka, dumating ang isa pang programmer sa trabaho. Gumagawa siya ng sarili niyang Pangunahing klase, kung saan sinimulan niyang gamitin ang Cat class na isinulat mo.
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "";
cat.age = -1000;
cat.weight = 0;
}
}
Hindi mahalaga kung bakit niya ito ginawa at kung paano ito nangyari (baka pagod ang lalaki o kulang sa tulog). May ibang bagay na mahalaga: ang aming kasalukuyang klase ng Cat ay nagbibigay-daan sa mga field na magtalaga ng mga talagang nakakabaliw na halaga. Bilang resulta, ang programa ay may mga bagay na may di-wastong estado (tulad ng pusang ito na -1000 taong gulang). Kaya anong pagkakamali ang ginawa namin noong idineklara ang aming klase? Inilantad namin ang data ng aming klase. Ang pangalan, edad at mga patlang ng timbang ay pampubliko. Maa-access ang mga ito kahit saan sa programa: gumawa lang ng Cat object at sinumang programmer ay may direktang access sa data nito sa pamamagitan ng dot ( . ) operator
Cat cat = new Cat();
cat.name = "";
Dito namin direktang ina-access ang field ng pangalan at itinatakda ang halaga nito. Kailangan naming kahit papaano ay protektahan ang aming data mula sa hindi tamang panlabas na interference. Ano ang kailangan nating gawin iyon? Una, ang lahat ng instance variable (mga field) ay dapat markahan ng pribadong modifier. Pribado ang pinakamahigpit na access modifier sa Java. Kapag nagawa mo na ito, ang mga field ng klase ng Cat ay hindi maa-access sa labas ng klase.
public class Cat {
private String name;
private int age;
private int weight;
public Cat(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
public Cat() {
}
public void sayMeow() {
System.out.println("Meow!");
}
}
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "";//error! The Cat class's name field is private!
}
}
Nakikita ito ng compiler at agad na bumubuo ng isang error. Ngayon ang mga patlang ay uri ng protektado. Ngunit lumalabas na na-shut down namin ang pag-access marahil masyadong mahigpit: hindi ka makakakuha ng bigat ng kasalukuyang pusa sa programa, kahit na kailangan mo. Hindi rin ito isang opsyon. Tulad nito, ang aming klase ay mahalagang hindi magagamit. Sa isip, kailangan nating payagan ang ilang uri ng limitadong pag-access:
- Ang ibang mga programmer ay dapat na makalikha ng mga bagay na Cat
- Dapat nilang mabasa ang data mula sa mga umiiral nang bagay (halimbawa, kunin ang pangalan o edad ng isang kasalukuyang pusa)
- Posible rin na magtalaga ng mga halaga ng field. Ngunit sa paggawa nito, ang mga wastong halaga lamang ang dapat pahintulutan. Ang aming mga bagay ay dapat na protektahan mula sa mga di-wastong halaga (hal. edad = -1000, atbp.).
public class Cat {
private String name;
private int age;
private int weight;
public Cat(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
public Cat() {
}
public void sayMeow() {
System.out.println("Meow!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
Tulad ng nakikita mo, mukhang medyo simple :) Ang kanilang mga pangalan ay kadalasang binubuo ng "get"/"set" kasama ang pangalan ng nauugnay na field. Halimbawa, ibinabalik ng getWeight() method ang value ng weight field para sa object kung saan ito tinatawag. Narito ang hitsura nito sa isang programa:
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
String smudgeName = smudge.getName();
int smudgeAge = smudge.getAge();
int smudgeWeight = smudge.getWeight();
System.out.println("Cat's name: " + smudgeName);
System.out.println("Cat's age: " + smudgeAge);
System.out.println("Cat's weight: " + smudgeWeight);
}
}
Output ng console:
Cat's name: Smudge
Cat's age: 5
Cat's weight: 4
Ngayon isa pang klase ( Main ) ang makaka-access sa mga field ng Cat , ngunit sa pamamagitan lamang ng mga getter. Tandaan na ang mga getter ay may pampublikong access modifier, ibig sabihin, available ang mga ito kahit saan sa programa. Ngunit ano ang tungkol sa pagtatalaga ng mga halaga? Ito ay para sa mga pamamaraan ng setter
public void setName(String name) {
this.name = name;
}
Tulad ng makikita mo, ang mga ito ay simple din. Tinatawag namin ang setName() method sa isang Cat object, nagpapasa ng string bilang argument, at ang string ay itinalaga sa field ng pangalan ng object.
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
System.out.println("Cat's original name: " + smudge.getName());
smudge.setName("Mr. Smudge");
System.out.println("Cat's new name: " + smudge.getName());
}
}
Dito ginagamit namin ang parehong mga getter at setter. Una, gumagamit kami ng getter para makuha at ipakita ang orihinal na pangalan ng pusa. Pagkatapos, gumagamit kami ng setter para magtalaga ng bagong pangalan ("Mr. Smudge"). At pagkatapos ay muli naming ginagamit ang getter upang makuha ang pangalan (para tingnan kung talagang nagbago ito). Output ng console:
Cat's original name: Smudge
Cat's new name: Mr. Smudge
Kaya ano ang pagkakaiba? Maaari pa rin kaming magtalaga ng mga di-wastong halaga sa mga field kahit na mayroon kaming mga setter:
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
smudge.setAge(-1000);
System.out.println("Smudge's age: " + smudge.getAge());
}
}
Output ng console:
Smudge's age: -1000 years
Ang pagkakaiba ay ang isang setter ay isang ganap na pamamaraan. At hindi tulad ng isang field, hinahayaan ka ng isang paraan na isulat ang lohika ng pag-verify na kinakailangan upang maiwasan ang mga hindi katanggap-tanggap na halaga. Halimbawa, madali mong mapipigilan ang isang negatibong numero na maitalaga bilang isang edad:
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
System.out.println("Error! Age can't be negative!");
}
}
At ngayon ang aming code ay gumagana nang tama!
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
smudge.setAge(-1000);
System.out.println("Smudge's age: " + smudge.getAge());
}
}
Output ng console:
Error! Age can't be negative!
Smudge's age: 5 years
Sa loob ng setter, gumawa kami ng paghihigpit na nagpoprotekta sa amin mula sa pagtatangkang magtakda ng di-wastong data. Ang edad ni Smudge ay hindi nabago. Dapat palagi kang lumikha ng mga getter at setter. Kahit na walang mga paghihigpit sa kung anong mga halaga ang maaaring gawin ng iyong mga patlang, ang mga pamamaraan ng katulong na ito ay hindi makakasama. Isipin ang sumusunod na sitwasyon: ikaw at ang iyong mga kasamahan ay nagsusulat ng isang programa nang magkasama. Gumawa ka ng klase ng Cat na may mga pampublikong field. Ang lahat ng mga programmer ay gumagamit ng mga ito gayunpaman gusto nila. At pagkatapos ay isang magandang araw ay napagtanto mo: "Crap, sa malao't madali ay maaaring may aksidenteng magtalaga ng negatibong numero sa timbang! Kailangan nating gumawa ng mga setter at gawing pribado ang lahat ng field!" Gawin mo lang iyon, at agad na sinira ang lahat ng code na isinulat ng iyong mga kasamahan. Pagkatapos ng lahat, sila ayDirektang mga field ng pusa .
cat.name = "Behemoth";
At ngayon ang mga patlang ay pribado at ang compiler ay nagbubuga ng isang grupo ng mga error!
cat.name = "Behemoth";//error! The Cat class's name field is private!
Sa kasong ito, mas mahusay na itago ang mga patlang at lumikha ng getter at setter mula sa simula. Ginamit sana ng lahat ng kasamahan mo. At kung huli mong napagtanto na kailangan mong higpitan ang mga halaga ng field, maaari mo na lang isulat ang tseke sa loob ng setter. At walang masisira ang code ng sinuman. Siyempre, kung gusto mong maging "read only" ang access sa isang field, makakagawa ka lang ng getter para dito. Ang mga pamamaraan lamang ang dapat na available sa labas (ibig sabihin, sa labas ng iyong klase). Dapat nakatago ang data. Maaari tayong gumawa ng paghahambing sa isang mobile phone. Isipin na sa halip na ang karaniwang nakapaloob na mobile phone, binigyan ka ng isang telepono na may bukas na case, na may lahat ng uri ng nakausli na mga wire, circuit, atbp. Ngunit gumagana ang telepono: kung susubukan mo nang husto at sundutin ang mga circuit, maaari ka ring maging marunong tumawag. Pero ikaw'
GO TO FULL VERSION