Helló! Az előző előadásokon már megtanultad, hogyan deklaráld saját, teljes értékű osztályaidat metódusokkal és mezőkkel. A mai leckében a Java gettereiről és szettereiről fogunk beszélni. Ez komoly előrelépés, jól sikerült! De most el kell mondanom egy kellemetlen igazságot. Nem deklaráltuk megfelelően az óráinkat! Miért? Első ránézésre a következő osztályban nincsenek hibák:
Ezek a nevek a "get" (azaz "egy mező értékének meghatározására szolgáló módszer") és "set" (azaz "egy mező értékének beállítására szolgáló módszer") szavakból származnak. Nézzük meg, hogyan néznek ki a Cat osztályunkban :
Ehelyett a gyártó egy interfészt ad: a felhasználó egyszerűen beírja a megfelelő számjegyeket, megnyomja a zöld hívás gombot, és a hívás megkezdődik. Nem érdekli, mi történik belül az áramkörökkel és vezetékekkel, vagy hogy hogyan végzik el a munkájukat. Ebben a példában a vállalat korlátozza a hozzáférést a telefon "belseihez" (adatok), és csak egy interfészt (módszereket) tesz közzé. Ennek eredményeként a felhasználó azt kapja, amit akart (a hívás lehetőségét), és biztosan nem tör el semmit. A tanultak megerősítése érdekében javasoljuk, hogy nézzen meg egy videóleckét a Java-tanfolyamról
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!");
}
}
De igen. Képzeld el, hogy a munkahelyeden ülsz, és ezt a macskaosztályt a macskák képviseletére írod. És akkor mész haza. Amíg te távol vagy, egy másik programozó érkezik a munkahelyére. Létrehozza saját főosztályát , ahol elkezdi használni az általad írt Cat osztályt.
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "";
cat.age = -1000;
cat.weight = 0;
}
}
Nem mindegy, hogy miért tette és hogyan történt (lehet, hogy a srác fáradt vagy nem aludt eleget). Valami más is számít: a jelenlegi Cat osztályunk lehetővé teszi a mezőkhöz teljesen őrült értékeket rendelni. Ennek eredményeként a programban vannak érvénytelen állapotú objektumok (például ez a macska, amely -1000 éves). Tehát milyen hibát követtünk el az osztályunk bejelentésekor? Kitettük osztályunk adatait. A név, kor és súly mezők nyilvánosak. Bárhol elérhetők a programban: egyszerűen hozzon létre egy Cat objektumot, és bármely programozó közvetlenül hozzáférhet az adataihoz a pont ( . ) operátoron keresztül.
Cat cat = new Cat();
cat.name = "";
Itt közvetlenül elérjük a név mezőt, és beállítjuk az értékét. Valahogy meg kell védenünk adatainkat a nem megfelelő külső beavatkozásoktól. Mire van szükségünk ehhez? Először minden példányváltozót (mezőt) meg kell jelölni a privát módosítóval. A privát a Java legszigorúbb hozzáférés-módosítója. Ha ezt megtette, a Cat osztály mezői nem lesznek elérhetők az osztályon kívül.
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!
}
}
A fordító ezt látja, és azonnal hibát generál. Most a mezők védettek. De kiderült, hogy talán túl szorosan zártuk le a hozzáférést: egy meglévő macska súlyát nem lehet a programban megadni, még akkor sem, ha muszáj. Ez szintén nem opció. Így az osztályunk gyakorlatilag használhatatlan. Ideális esetben engedélyeznünk kell valamilyen korlátozott hozzáférést:
- Más programozóknak képesnek kell lenniük Cat objektumok létrehozására
- Képesnek kell lenniük meglévő objektumok adatainak olvasására (például megtudni egy meglévő macska nevét vagy életkorát).
- Lehetővé kell tenni a mezőértékek hozzárendelését is. Ennek során azonban csak érvényes értékeket szabad megengedni. Tárgyainkat védeni kell az érvénytelen értékektől (pl. kor = -1000 stb.).
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;
}
}
Amint látja, elég egyszerűnek tűnnek :) A nevük gyakran a "get"/"set" és a megfelelő mező nevéből áll. Például a getWeight() metódus visszaadja a meghívott objektum súlymezőjének értékét. Így néz ki egy programban:
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);
}
}
Konzol kimenet:
Cat's name: Smudge
Cat's age: 5
Cat's weight: 4Most egy másik osztály ( Main ) érheti el a Cat mezőket, de csak gettereken keresztül. Vegye figyelembe, hogy a getterek rendelkeznek a nyilvános hozzáférés módosítóval, azaz a program bármely pontjáról elérhetők. De mi a helyzet az értékek hozzárendelésével? Erre valók a setter módszerek
public void setName(String name) {
this.name = name;
}
Mint látható, ezek is egyszerűek. Meghívjuk a setName() metódust egy Cat objektumon, egy karakterláncot adunk át argumentumként, és a karakterlánc hozzá van rendelve az objektum névmezőjéhez.
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());
}
}
Itt gettereket és settereket is használunk. Először egy gettert használunk, hogy megkapjuk és megjelenítsük a macska eredeti nevét. Ezután egy setter segítségével új nevet adunk ("Mr. Smudge"). Ezután még egyszer használjuk a gettert, hogy megkapjuk a nevet (ellenőrizzük, hogy valóban megváltozott-e). Konzol kimenet:
Cat's original name: Smudge
Cat's new name: Mr. SmudgeSzóval mi a különbség? Még akkor is hozzárendelhetünk érvénytelen értékeket a mezőkhöz, ha vannak beállítóink:
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());
}
}
Konzol kimenet:
Smudge's age: -1000 yearsA különbség az, hogy a szetter egy teljes értékű módszer. A mezőkkel ellentétben a metódusok lehetővé teszik az elfogadhatatlan értékek megakadályozásához szükséges ellenőrzési logika megírását. Könnyedén megakadályozhatja például, hogy egy negatív szám életkorként legyen hozzárendelve:
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
System.out.println("Error! Age can't be negative!");
}
}
És most a kódunk megfelelően működik!
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());
}
}
Konzol kimenet:
Error! Age can't be negative!
Smudge's age: 5 yearsA beállítón belül létrehoztunk egy korlátozást, amely megvédett minket az érvénytelen adatok beállításának kísérletétől. Smudge életkora nem változott. Mindig hozzon létre gettereket és settereket. Még ha nincsenek korlátozások arra vonatkozóan, hogy a mezők milyen értékeket vehetnek fel, ezek a segédmódszerek nem ártanak. Képzelje el a következő helyzetet: Ön és kollégái közösen írnak programot. Létrehoz egy Cat osztályt nyilvános mezőkkel. Minden programozó úgy használja őket, ahogy akarja. És aztán egy szép napon rájössz: "A szar, előbb-utóbb valaki véletlenül negatív számot rendel a súlyhoz! Szállítókat kell létrehoznunk, és az összes mezőt priváttá kell tenni!" Ön éppen ezt teszi, és azonnal feltöri a kollégái által írt összes kódot. Végül is ők'Macska mezők közvetlenül.
cat.name = "Behemoth";
És most a mezők privátak, és a fordító egy csomó hibát kidob!
cat.name = "Behemoth";//error! The Cat class's name field is private!
Ebben az esetben jobb lenne elrejteni a mezőket, és már az elején létrehozni gettereket és szettereket. Minden kollégája használta volna őket. És ha későn vette észre, hogy valahogy korlátoznia kell a mezőértékeket, akkor a csekket beírhatta volna a beállítóba. És senkinek a kódja nem törne össze. Természetesen, ha azt szeretné, hogy egy mezőhöz csak "csak olvasható" legyen a hozzáférés, akkor csak egy gettert hozhat létre hozzá. Csak a metódusok legyenek elérhetők kívülről (azaz az osztályon kívül). Az adatokat el kell rejteni. Összehasonlíthatnánk egy mobiltelefonnal. Képzeld el, hogy a szokásos zárt mobiltelefon helyett egy nyitott tokkal ellátott telefont kaptál, mindenféle kilógó vezetékekkel, áramkörökkel stb. De a telefon működik: ha nagyon próbálkozol és piszkálod az áramköröket, még az is lehet, hogy tud hívást kezdeményezni. de te
GO TO FULL VERSION