CodeGym /Java blogg /Slumpmässig /Getters och setters
John Squirrels
Nivå
San Francisco

Getters och setters

Publicerad i gruppen
Hallå! I tidigare föreläsningar har du redan lärt dig hur du deklarerar dina egna fullfjädrade klasser med metoder och fält. I dagens lektion kommer vi att prata om Getters och Setters i Java. Detta är allvarliga framsteg, bra jobbat! Men nu måste jag berätta en obehaglig sanning. Vi har inte deklarerat våra klasser korrekt! Varför? Vid första anblicken har följande klass inga misstag:

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!");
   }
}
Men det gör det. Föreställ dig att du sitter på jobbet och skriver den här kattklassen för att representera katter. Och så går du hem. Medan du är borta kommer en annan programmerare till jobbet. Han skapar sin egen huvudklass , där han börjar använda kattklassen du skrev.

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
Det spelar ingen roll varför han gjorde det och hur det gick till (kanske är killen trött eller har inte fått tillräckligt med sömn). Något annat spelar roll: vår nuvarande Cat- klass tillåter att fält tilldelas helt galna värden. Som ett resultat har programmet objekt med ett ogiltigt tillstånd (som denna katt som är -1000 år gammal). Så vilket fel gjorde vi när vi deklarerade vår klass? Vi avslöjade vår klasss data. Fälten för namn, ålder och vikt är offentliga. De kan nås var som helst i programmet: skapa helt enkelt ett Cat- objekt och vilken programmerare som helst har direkt åtkomst till dess data via punktoperatorn ( . )

Cat cat = new Cat();
cat.name = "";
Här kommer vi direkt åt namnfältet och ställer in dess värde. Vi måste på något sätt skydda våra data från olämplig extern störning. Vad behöver vi för att göra det? Först måste alla instansvariabler (fält) markeras med den privata modifieraren. Privat är den strängaste åtkomstmodifieraren i Java. När du har gjort detta kommer fälten i Cat -klassen inte att vara tillgängliga utanför klassen.

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!
   }
}
Kompilatorn ser detta och genererar omedelbart ett fel. Nu är fälten liksom skyddade. Men det visar sig att vi har stängt av åtkomsten kanske för hårt: du kan inte få in en befintlig katts vikt i programmet, även om du behöver det. Detta är inte heller ett alternativ. Som det är är vår klass i princip oanvändbar. Helst måste vi tillåta någon form av begränsad åtkomst:
  • Andra programmerare bör kunna skapa Cat- objekt
  • De ska kunna läsa data från befintliga objekt (till exempel få namnet eller åldern på en befintlig katt)
  • Det ska också vara möjligt att tilldela fältvärden. Men då bör endast giltiga värden tillåtas. Våra objekt bör skyddas från ogiltiga värden (t.ex. ålder = -1000, etc.).
Det är en bra lista med krav! I verkligheten uppnås allt detta enkelt med speciella metoder som kallas getters och setters.
Getters och setters - 2
Dessa namn kommer från "get" (dvs "metod för att få värdet av ett fält") och "set" (dvs "metod för att ställa in värdet på ett fält"). Låt oss se hur de ser ut i vår Cat- klass :

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;
   }
}
Som du kan se ser de ganska enkla ut :) Deras namn består ofta av "get"/"set" plus namnet på relevant fält. Till exempel returnerar metoden getWeight() värdet på viktfältet för objektet som det anropas på. Så här ser det ut i ett program:

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);
   }
}
Konsolutgång:
Cat's name: Smudge
Cat's age: 5
Cat's weight: 4
Nu kan en annan klass ( Main ) komma åt Cat- fälten, men bara genom getters. Observera att getters har public access-modifieraren, dvs de är tillgängliga från var som helst i programmet. Men hur är det med att tilldela värden? Det är vad sättermetoder är till för

public void setName(String name) {
   this.name = name;
}
Som du kan se är de också enkla. Vi anropar metoden setName() på ett Cat- objekt, skickar en sträng som ett argument och strängen tilldelas objektets namnfält.

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());
   }
}
Här använder vi både getters och setters. Först använder vi en getter för att få och visa kattens ursprungliga namn. Sedan använder vi en setter för att tilldela ett nytt namn ("Mr. Smudge"). Och sedan använder vi gettern igen för att få namnet (för att kontrollera om det verkligen har ändrats). Konsolutgång:
Cat's original name: Smudge
Cat's new name: Mr. Smudge
Så vad är skillnaden? Vi kan fortfarande tilldela ogiltiga värden till fält även om vi har setters:

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());
   }
}
Konsolutgång:
Smudge's age: -1000 years
Skillnaden är att en setter är en fullfjädrad metod. Och till skillnad från ett fält låter en metod dig skriva den verifieringslogik som krävs för att förhindra oacceptabla värden. Du kan till exempel enkelt förhindra att ett negativt tal tilldelas som en ålder:

public void setAge(int age) {
   if (age >= 0) {
       this.age = age;
   } else {
       System.out.println("Error! Age can't be negative!");
   }
}
Och nu fungerar vår kod korrekt!

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());
   }
}
Konsolutgång:
Error! Age can't be negative!
Smudge's age: 5 years
Inuti sättaren skapade vi en begränsning som skyddade oss från försöket att ställa in ogiltiga data. Smudges ålder ändrades inte. Du bör alltid skapa getters och setters. Även om det inte finns några begränsningar för vilka värden dina fält kan ta, kommer dessa hjälpmetoder inte att skada. Föreställ dig följande situation: du och dina kollegor skriver ett program tillsammans. Du skapar en Cat- klass med offentliga fält. Alla programmerare använder dem hur de vill. Och så en vacker dag inser du: "Fan, förr eller senare kan någon av misstag tilldela vikten ett negativt tal! Vi måste skapa sättare och göra alla fält privata!" Du gör just det och bryter omedelbart all kod som skrivits av dina kollegor. När allt kommer omkring, deKattfält direkt.

cat.name = "Behemoth";
Och nu är fälten privata och kompilatorn spyr ut en massa fel!

cat.name = "Behemoth";//error! The Cat class's name field is private!
I det här fallet skulle det vara bättre att dölja fälten och skapa getter och setters från första början. Alla dina kollegor skulle ha använt dem. Och om du sent insåg att du behövde begränsa fältvärdena på något sätt, kunde du bara ha skrivit checken inuti sättaren. Och ingens kod skulle brytas. Naturligtvis, om du vill att tillgången till ett fält bara ska vara "skrivskyddad", kan du bara skapa en getter för det. Endast metoder ska vara tillgängliga externt (dvs utanför din klass). Data bör döljas. Vi skulle kunna göra en jämförelse med en mobiltelefon. Föreställ dig att du istället för den vanliga inneslutna mobiltelefonen fick en telefon med ett öppet fodral, med alla möjliga utstickande ledningar, kretsar etc. Men telefonen fungerar: om du verkligen försöker och petar i kretsarna kan du till och med vara kunna ringa ett samtal. Men du'
Getters och sättare - 3
Istället ger tillverkaren dig ett gränssnitt: användaren anger helt enkelt rätt siffror, trycker på den gröna samtalsknappen och samtalet börjar. Hon bryr sig inte om vad som händer inuti med kretsarna och ledningarna, eller hur de får sitt jobb gjort. I det här exemplet begränsar företaget åtkomsten till telefonens "insida" (data) och exponerar endast ett gränssnitt (metoder). Som ett resultat får användaren vad hon ville ha (möjligheten att ringa) och kommer definitivt inte att bryta något inuti. För att förstärka det du lärde dig föreslår vi att du tittar på en videolektion från vår Java-kurs
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION