JavaRush /Blog Java /Random-PL /Gettery i settery

Gettery i settery

Opublikowano w grupie Random-PL
Cześć! Na poprzednich wykładach nauczyłeś się już tworzyć własne, pełnowartościowe zajęcia, z polami i metodami. To poważny postęp, brawo! Ale teraz muszę wyznać Ci nieprzyjemną prawdę. Nie stworzyliśmy naszych zajęć całkiem dobrze! Dlaczego? Na pierwszy rzut oka nie ma w tej klasie błędów:
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("Miauczeć!");
   }
}
W rzeczywistości istnieje. Wyobraź sobie, że siedząc w pracy, napisałeś taką klasę Cat, oznaczającą koty. I poszedł do domu. Kiedy Ciebie nie było, do pracy przyszedł inny programista, stworzył własną klasę Main, w której zaczął korzystać z klasy, którą napisałeś Cat.
public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
Nie ma znaczenia, dlaczego to zrobił i jak to się stało: może dana osoba była zmęczona lub nie wysypiała się. Ważna jest jeszcze jedna rzecz: nasza obecna klasa Catpozwala na przypisanie szalonych wartości do pól. W rezultacie program zawiera obiekty w nieprawidłowym stanie, jak na przykład ten kot w wieku -1000 lat. Jaki błąd ostatecznie popełniliśmy? Kiedy tworzyliśmy klasę, ujawniliśmy jej dane. Pola namei ageweightw domenie publicznej. Dostęp do nich można uzyskać w dowolnym miejscu programu: wystarczy utworzyć obiekt Cat- i to wszystko, każdy programista ma dostęp do jego danych bezpośrednio poprzez operator „ .
Cat cat = new Cat();
cat.name = "";
Tutaj mamy bezpośredni dostęp do pola namei ustawiamy jego wartość. Musimy w jakiś sposób chronić nasze dane przed niepoprawną ingerencją z zewnątrz. Co jest do tego potrzebne? Po pierwsze, wszystkie zmienne instancji (pola) muszą być oznaczone modyfikatorem private. Prywatny to najsurowszy modyfikator dostępu w Javie. Jeżeli z niej skorzystasz, pola klasy Catnie będą dostępne poza nią.
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("Miauczeć!");
   }
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";//błąd! Pole name w klasie Cat ma dostęp prywatny!
   }
}
Kompilator widzi to i natychmiast generuje błąd. Teraz pola wydają się być chronione. Okazuje się jednak, że dostęp do nich jest „szczelnie” zamknięty: program nie jest w stanie w razie potrzeby uzyskać nawet wagi istniejącego kota. To również nie wchodzi w grę: w tej formie nasza klasa jest praktycznie niemożliwa do użycia. Idealnie byłoby, gdybyśmy umożliwili pewien ograniczony dostęp do danych:
  • Inni programiści powinni mieć możliwość tworzenia obiektówCat
  • Powinni umieć odczytać dane z już istniejących obiektów (na przykład uzyskać imię lub wiek już istniejącego kota)
  • Powinna istnieć także możliwość przypisania wartości polom. Ale jednocześnie - tylko prawidłowe wartości. Nasze przedmioty należy chronić przed niewłaściwymi (żadnych „wiek = -1000 lat” i tym podobnych).
Lista wymagań jest przyzwoita! Ale tak naprawdę wszystko to można łatwo osiągnąć za pomocą specjalnych metod - pobierających i ustawiających .
Gettery i settery - 2
Nazwa pochodzi od angielskiego „ get ” - „ otrzymać ” (tj. „Metoda uzyskiwania wartości pola”) i set - „ set ” (tj. „Metoda ustawiania wartości pola”). Zobaczmy jak one wyglądają na przykładzie naszej klasy 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("Miauczeć!");
   }

   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;
   }
}
Jak widać wszystko jest dość proste :) Ich nazwy składają się najczęściej ze słowa get/set + nazwy pola, za które odpowiadają. Na przykład metoda getWeight()zwraca wartość pola weightobiektu, dla którego została wywołana. Tak to wygląda w programie:
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);
       String barsikName = barsik.getName();
       int barsikAge = barsik.getAge();
       int barsikWeight = barsik.getWeight();

       System.out.println(„Imię kota:” + barsikName);
       System.out.println(„Wiek kota:” + barsikAge);
       System.out.println(„Waga kota:” + barsikWeight);
   }
}
Wyjście konsoli:

Nazwa кота: Барсик
Возраст кота: 5
Вес кота: 4
Teraz z innej klasy ( Main) jest dostęp do pól Cat, ale tylko poprzez gettery . Należy pamiętać, że moduły pobierające mają modyfikator dostępu public, co oznacza, że ​​są dostępne z dowolnego miejsca w programie. A co z przypisywaniem wartości? Odpowiadają za to metody ustawiające
public void setName(String name) {
   this.name = name;
}
Ich praca, jak widać, jest również prosta. Wywołujemy metodę setName()na obiekcie Cat, przekazujemy mu jako argument ciąg znaków, a ciąg ten jest przypisywany do pola namenaszego obiektu.
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);

       System.out.println(„Oryginalne imię kota to” + barsik.getName());
       barsik.setName("Bazylia");
       System.out.println(„Nowe imię kota...” + barsik.getName());
   }
}
Tutaj użyliśmy zarówno getterów, jak i setterów. Najpierw za pomocą gettera otrzymaliśmy i wyprowadziliśmy na konsolę początkową nazwę kota. Następnie za pomocą setera nameprzypisano do jego pola nową wartość - „Wasilij”. A potem, używając gettera, ponownie otrzymaliśmy nazwę, aby sprawdzić, czy rzeczywiście się zmieniła. Wyjście konsoli:

Изначальное Nazwa кота — Барсик
Новое Nazwa кота — ВасLubй
Wydawałoby się, jaka jest różnica? Możemy także przypisać niepoprawne wartości do pól obiektowych, nawet jeśli mamy setery:
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);
       barsik.setAge(-1000);

       System.out.println(„Wiek Barsika -” + barsik.getAge() + „lata”);
   }
}
Wyjście konsoli:

Возраст Барсика — -1000 лет
Różnica polega na tym, że seter jest metodą pełnoprawną . W metodzie, w przeciwieństwie do pola, możesz umieścić logikę weryfikacji potrzebną do zapobiegania niedopuszczalnym wartościom. Na przykład możesz łatwo wyłączyć przypisywanie liczby ujemnej jako wieku:
public void setAge(int age) {
   if (age >= 0) {
       this.age = age;
   } else {
       System.out.println(„Błąd! Wiek nie może być ujemny!”);
   }
}
I teraz nasz kod działa poprawnie!
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);
       barsik.setAge(-1000);

       System.out.println(„Wiek Barsika -” + barsik.getAge() + „lata”);
   }
}
Wyjście konsoli:

Ошибка! Возраст не может быть отрицательным числом!
Возраст Барсика — 5 лет
Wewnątrz setera znajduje się ograniczenie, które chroni przed próbami ustawienia błędnych danych. Wiek Barsika pozostał niezmieniony. Zawsze należy tworzyć metody pobierające i ustawiające. Nawet jeśli Twoje pola nie mają ograniczeń co do możliwych wartości, nie spowoduje to żadnej szkody. Wyobraź sobie sytuację: Ty i Twoi współpracownicy piszecie wspólnie program. Utworzyłeś klasę Catz polami publicznymi i wszyscy programiści używają ich tak, jak chcą. I wtedy pewnego pięknego dnia dociera do ciebie: „Cholera, wcześniej czy później ktoś może przypadkowo przypisać do zmiennej liczbę ujemną weight! Musimy stworzyć ustawienia ustawiające i ustawić wszystkie pola jako prywatne!” Tworzysz je, a cały kod napisany przez Twoich kolegów natychmiast się psuje. W końcu napisali już sporo kodu umożliwiającego Catbezpośredni dostęp do pól.
cat.name = "Hipopotam";
A teraz pola stały się prywatne i kompilator generuje masę błędów!
cat.name = "Hipopotam";//błąd! Pole name klasy Cat ma dostęp prywatny!
W takiej sytuacji lepiej byłoby ukryć pola i od początku stworzyć gettery-setery . Wszyscy twoi koledzy by z nich korzystali, a jeśli późno dotarłoby do ciebie, że musisz ograniczyć wartości pól, po prostu dodałbyś zaznaczenie wewnątrz ustawiacza. I nikt nie złamałby już napisanego kodu. Oczywiście, jeśli chcesz mieć dostęp tylko do odczytu do określonego pola, możesz utworzyć dla niego jeden moduł pobierający. „Na zewnątrz”, czyli poza klasą, powinny być dostępne tylko metody. Dane muszą być ukryte.
Gettery i settery - 4
Można dokonać analogii z telefonem komórkowym. Wyobraź sobie, że zamiast włączonego zwykłego telefonu komórkowego, dostałeś telefon z otwartą obudową, w której znajdują się wszystkie przewody, obwody itp. wystaje. Telefon działa: jeśli bardzo się postarasz i pobawisz się schematami, może nawet uda ci się wykonać połączenie. Ale prawdopodobnie po prostu to złamiesz. Zamiast tego firma produkcyjna zapewnia interfejs: klient po prostu wybiera żądane numery, naciska zielony przycisk na słuchawce i rozpoczyna się połączenie. I nie interesuje go, co dzieje się wewnątrz z obwodami i przewodami oraz jak wykonują swoje zadanie. W tym przykładzie firma ograniczyła dostęp do „wewnętrznych elementów” (danych) telefonu i pozostawiła na zewnątrz jedynie interfejs (metody). Dzięki temu klient dostanie to czego chciał (zadzwoni) i na pewno niczego w środku nie stłucze.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION