CodeGym /Java blog /Véletlen /Getterek és szetterek
John Squirrels
Szint
San Francisco

Getterek és szetterek

Megjelent a csoportban
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:

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.).
Ez egy tisztességes követelménylista! A valóságban mindez könnyen elérhető speciális módszerekkel, úgynevezett getterekkel és szetterekkel.
Getterek és szetterek – 2
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 :

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: 4
Most 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. Smudge
Szó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 years
A 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 years
A 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
Getterek és szetterek – 3
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
Hozzászólások
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION