CodeGym /Java блог /Случаен /Геттери и сетери
John Squirrels
Ниво
San Francisco

Геттери и сетери

Публикувано в групата
Здравейте! В предишните лекции вече научихте How да декларирате свои собствени пълноценни класове с методи и полета. В днешния урок ще говорим за Getters и Setters в Java. Това е сериозен напредък, браво! Но сега трябва да ви кажа една неприятна истина. Не сме декларирали нашите класове правилно! Защо? На пръв поглед следният клас няма ниHowви грешки:

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!");
   }
}
Но го прави. Представете си, че седите на работа и пишете този клас Cat за представяне на котки. И след това се прибираш. Докато ви няма, друг програмист идва на работа. Той създава свой собствен главен клас, където започва да използва класа Cat , който сте написали.

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
Няма meaning защо го е направил и How се е случило (може би човекът е уморен or не е спал достатъчно). Нещо друго има meaning: сегашният ни клас Cat позволява на полета да се присвояват абсолютно безумни стойности. В резултат на това програмата има обекти с невалидно състояние (като тази котка, която е на -1000 години). И така, Howва грешка направихме, когато декларирахме нашия клас? Разкрихме данните на нашия клас. Полетата за име, възраст и тегло са публични. Те могат да бъдат достъпни навсякъде в програмата: просто създайте Cat обект и всеки програмист има директен достъп до неговите данни чрез оператора точка ( . ).

Cat cat = new Cat();
cat.name = "";
Тук имаме директен достъп до полето за име и задаваме неговата стойност. Трябва по няHowъв начин да защитим данните си от неправилна външна намеса. Какво ни трябва за това? Първо, всички променливи на екземпляр (полета) трябва да бъдат маркирани с частния модификатор. Private е най-строгият модификатор на достъп в Java. След като направите това, полетата на класа Cat няма да бъдат достъпни извън класа.

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!
   }
}
Компилаторът вижда това и веднага генерира грешка. Сега нивите са нещо като защитени. Но се оказва, че сме затворor достъпа може би твърде строго: не можете да получите теглото на съществуваща котка в програмата, дори и да имате нужда. Това също не е опция. Както е, нашият клас е по същество неизползваем. В идеалния случай трябва да разрешим няHowъв вид ограничен достъп:
  • Други програмисти трябва да могат да създават Cat обекти
  • Те трябва да могат да четат данни от съществуващи обекти (например да получат името or възрастта на съществуваща котка)
  • Също така трябва да е възможно да се задават стойности на полета. Но при това трябва да се допускат само валидни стойности. Нашите обекти трябва да бъдат защитени от невалидни стойности (напр. възраст = -1000 и т.н.).
Това е прorчен списък с изисквания! В действителност всичко това се постига лесно със специални методи, наречени гетери и сетери.
Геттери и сетери - 2
Тези имена идват от "get" (т.е. "метод за получаване на стойността на поле") и "set" (т.е. "метод за задаване на стойността на поле"). Нека видим How изглеждат в нашия клас Cat :

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;
   }
}
Както можете да видите, те изглеждат доста прости :) Имената им често се състоят от "get"/"set" плюс името на съответното поле. Например методът getWeight() връща стойността на полето за тегло за обекта, към който е извикан. Ето How изглежда в програма:

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);
   }
}
Конзолен изход:
Cat's name: Smudge
Cat's age: 5
Cat's weight: 4
Сега друг клас ( Main ) има достъп до Cat полетата, но само чрез гетери. Обърнете внимание, че гетърите имат модификатора за публичен достъп, т.е. те са достъпни от всяка точка на програмата. Но Howво ще кажете за присвояването на стойности? За това са методите на сетер

public void setName(String name) {
   this.name = name;
}
Както можете да видите, те също са прости. Извикваме метода setName() на обект Cat , предаваме низ като аргумент и низът се присвоява на полето за име на обекта.

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());
   }
}
Тук използваме Howто гетери, така и сетери. Първо, използваме гетер, за да получим и покажем оригиналното име на котката. След това използваме сетер, за да зададем ново име („Mr. Smudge“). И след това използваме getter още веднъж, за да получим името (за да проверим дали наистина се е променило). Конзолен изход:
Cat's original name: Smudge
Cat's new name: Mr. Smudge
И така, Howва е разликата? Все още можем да присвоим невалидни стойности на полета, дори ако имаме сетери:

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());
   }
}
Конзолен изход:
Smudge's age: -1000 years
Разликата е, че сетерът е пълноценен метод. И за разлика от поле, методът ви позволява да напишете логиката за проверка, необходима за предотвратяване на неприемливи стойности. Например, можете лесно да предотвратите присвояването на отрицателно число като възраст:

public void setAge(int age) {
   if (age >= 0) {
       this.age = age;
   } else {
       System.out.println("Error! Age can't be negative!");
   }
}
И сега нашият code работи правилно!

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());
   }
}
Конзолен изход:
Error! Age can't be negative!
Smudge's age: 5 years
Вътре в настройката създадохме ограничение, което ни предпазваше от опити за задаване на невалидни данни. Възрастта на Smudge не е променена. Винаги трябва да създавате гетери и сетери. Дори и да няма ограничения за това Howви стойности могат да приемат вашите полета, тези помощни методи няма да навредят. Представете си следната ситуация: вие и вашите колеги пишете програма заедно. Създавате клас Cat с публични полета. Всички програмисти ги използват Howто си искат. И тогава в един прекрасен ден разбирате: „Мамка му, рано or късно някой може случайно да присвои отрицателно число на теглото! Трябва да създадем сетери и да направим всички полета частни!“ Правите точно това и незабавно разбивате целия code, написан от вашите колеги. В крайна сметка теКотешки полета директно.

cat.name = "Behemoth";
И сега полетата са лични и компилаторът бълва куп грешки!

cat.name = "Behemoth";//error! The Cat class's name field is private!
В този случай би било по-добре да скриете полетата и да създадете getter и setter от самото начало. Всички ваши колеги биха ги използвали. И ако сте разбрали със закъснение, че трябва по няHowъв начин да ограничите стойностите на полетата, можеше просто да напишете проверката в сетера. И ничий code няма да бъде разбит. Разбира се, ако искате достъпът до поле да бъде само "само за четене", можете да създадете само метод за получаване за него. Само методите трябва да са достъпни външно (т.е. извън вашия клас). Данните трябва да бъдат скрити. Можем да направим сравнение с мобилен телефон. Представете си, че instead of обичайния затворен мобилен телефон ви е даден телефон с отворен калъф, с всяHowви стърчащи кабели, вериги и т.н. Но телефонът работи: ако се постараете наистина много и пробиете веригите, може дори да сте може да се обади. Но ти'
Геттери и сетери - 3
Вместо това производителят ви предоставя интерфейс: потребителят просто въвежда правилните цифри, натиска зеления бутон за повикване и разговорът започва. Тя не се интересува Howво се случва вътре с веригите и кабелите or How си вършат работата. В този пример компанията ограничава достъпа до „вътрешностите“ на телефона (данните) и излага само интерфейс (методи). В резултат на това потребителят получава това, което иска (възможността да се обажда) и със сигурност няма да счупи нищо вътре. За да затвърдите наученото, ви предлагаме да гледате видео урок от нашия курс по Java
Коментари
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION