Sikerült megcsinálni az előző rész feladatát? Minden szuper lett? Naah, ne bólogass annyira! Nekem ez jött össze:
Szóval, amikor az Ember megissza az Innivalót, akkor bele akar kukkantani, hogy megtudja, mennyi a felszolgált méret, és mennyi az alkohol százalék. De hisz most tettük mindezeket gondosan private-á, és emiatt nem látja ezeket a mezőket! Akkor most mi legyen?
tehetjük vissza public-ra, de akkor nem csak kiolvasni, hanem írni is tudja mindenki. Lehetséges lenne olyan igyal() metódust csinálni, ami... khmm... megváltoztatja az Innivalót megivás előtt (beleköp? vagy egyéb rondaságokat csinál? Fúúúj!) Ezt hagyni persze szemantikai hiba lenne.
maradhat private-en, viszont akkor nem lehet hasznáni.
Mi a megoldás? A megoldás az, hogy olyan módon kellene ezeket az értékeket elérni, hogy:
Sajnos azonban a Java nem tud ilyet. Más nyelvek tudnak, a Delphi is tud, és a C# is kicsit okosabb ebben, de valahogy a Javaból ez kimaradt. Itt a problémára más megoldást eszeltek ki.
Ezeket a metódusokat úgy szokták elnevezni, hogy getValami(), mint például getName() ami a name értékét adná vissza. A get szó azt jelenti, hogy előszedni. Ezért ezeknek a közös neve getterek azaz előszedő metódusok.
Csináljunk egy ilyen gettert a végére:
public class Innivalo {
private double felszolgaltMeret=5; // dl
private double alkoholTartalomSzazalek=4; // %
private String nev;
protected Innivalo(String nev,double felszolgaltMeret,double alkoholTartalomSzazalek) {
this.nev=nev;
this.felszolgaltMeret=felszolgaltMeret;
this.alkoholTartalomSzazalek=alkoholTartalomSzazalek;
}
public String toString() {
return nev+", "+felszolgaltMeret+" deci, "+alkoholTartalomSzazalek+"%";
}
// ez itt a getter
public double getFelszolgaltMeret() {
return felszolgaltMeret;
}
}
Tehát a getFelszolgaltMeret az visszaadja a felszolgaltMeret értékét. De ezzel megváltoztatni nem lehet, szóval ez most csak-olvasható (vagy más néven read-only) lett így.
Csináld meg a másik tulajdonságra is a gettert! Igaziból az Eclipse segít ebben, kattingts a Source menüben a Generate Getters and Setters menüpontra:
Kapcsold be csak a getAlkoholSzazalek gettert, kattints az OK-ra és készen is vagy!
No ha ezzel megvagyunk, az Emberben kijavíthatjuk a hibát, és az
innivalo.felszolgaltMeret // ez volt a közvetlen hivatkozás a private mezőre
helyett
innivalo.getFelszolgaltMeret() // ez egy public getter
Tehát így néz ki készen:
public class Ember {
private double fogyasztottAlkohol=0;
private double alkoholTures=1;
private String nev;
private double ivottMennyiseg=0;
private List<Innivalo> innivalok=new ArrayList<>();
public Ember(String nev,double alkoholTures) {
this.nev=nev;
this.alkoholTures=alkoholTures;
}
public void igyal(Innivalo innivalo) {
innivalok.add(innivalo);
fogyasztottAlkohol+=innivalo.getFelszolgaltMeret()*innivalo.getAlkoholTartalomSzazalek()/100;
if (fogyasztottAlkohol>alkoholTures) {
throw new RuntimeException("Jajj, ez sok volt! "+nev+" kidolt!");
}
ivottMennyiseg+=innivalo.getFelszolgaltMeret();
if (ivottMennyiseg>10) { // ez akkor 1 liter, mert deciben számolunk
throw new RuntimeException(nev+" most feladta, mert szünetre van szüksége!");
}
}
public String toString() {
String eredmeny=nev+" megivott "+ivottMennyiseg+" deci italt, össz. "+fogyasztottAlkohol+" deci alkohol tartalom.\n";
for (Innivalo innivalo:innivalok) {
eredmeny+=" "+innivalo+"\n";
}
return eredmeny;
}
}
A get párja a set, ami azt jelenti, hogy valamit beállítani. A setName() metódus például a name tulajdonságot állítaná.
Ha például számunkra helyes lenne, hogy bárki átcimkézi a kitöltött italt, és új nevet ad a kannás bornak, akkor ahhoz egy ilyen setter tartozna:
public void setNev(String nev) {
this.nev = nev;
}
Az elv ugyanaz, mint a getternél: ez a metódus public, így kívülről meghívható. Mivel az osztályon belül van, ezért tudja írni az osztályon belüli private név mezőt.
Ha van egy tulajdonság, amit lehet írni is meg olvasni is kívülről, akkor miért nem tesszük simán publicra? Miért erőlködünk egy getterrel és egy setterrel?
Ez a kérdés nagyon logikus! A válasz az, hogy néha ilyenkor is praktikus egy setter, hiszen egy setter nem biztos, hogy csak beállítja egy tulajdonság értékét. Lehetséges, hogy ezen kívül más dolgot is fog csinálni.
Például, ha a képernyőre kiteszünk egy ablakot, akkor a setX() függvényt meghívva nem csak megváltozik az ablak példányban az x értéke, hanem ténylegesen odébb is rakja a képernyőn az ablakot. Ezt az extra dolgot ami történik, a setter simán meg tudja csinálni, hiszen a setter belsejébe ezt megírhatjuk. De ha csak az x tulajdonság lenne public, akkor azt ugyan átírhatjuk kívülről, de az ablak nem fog odébb menni attól, hogy a változó értékét piszkáljuk, hisz az csak egy változó.
A setter-getter koncepció tehát igaz, hogy macera, de egységsen működik mindenre:
A Java szigetek (ugye tudod, hogy az angol wikipedia mennyivel többet tud?) híres kávétermelő sziget. Állítólag a Java programnyelvet egy kávézóban találták ki, ezért pont kávéscsésze a logója, és sokszor találkozunk egyéb kávés utalásokkal is.
A bean jelentése bab - egész pontosan kávébab. Az alkotók logikája szerint egy babszem egy önálló zárt részegység, egy olyan osztály, ami vigyáz az adataira.
Tehát:
akkor az az osztály egy bean.
Ilyenekkel nagyon nagyon sokat fogunk találkozni, hiszen erre a logikára épül majd az összes Java-hoz adott osztály.