Sierpień 10, 2018

Settery i Gettery

Settery i Gettery

Choć może tytuł lekcji wygląda tajemniczo to jest on ściśle powiązany z poprzednią lekcją – z modyfikatorami dostępu. Settery i Gettery – a szczególnie gettery ułatwiają nam pewien sposób przysłania pól. W tej lekcji  będziemy skupiać się właśnie na przysłaniu pól.

Przypominasz sobie z pewnością modyfikator dostępu private – przysłania on wszystko tak, że metody i pola widzimy tylko z poziomu tej samej klasy. Przypuśćmy, że chcemy, aby dostep do pola był możliwy, a jego modyfikacja nie – co wtedy? Przykład trochę może teraz abstrakcyjny – weźmy przykład bardziej realistyczny.

Przypuśćmy, że mamy klasę User – przechowuje ona jakieś id, login, hasło oraz e-mail. Chcemy pozwolić na wyświetlanie id, loginu, hasła oraz e-mail – jednak chcemy zabronić modyfikacji id – ponieważ nasze założenie mówi, że id usera ma być unikalne. I co wtedy?

Wtedy z pomocą przychodzą nam tzw. Settery i Gettery. Czym, więc one są?

Co to jest…

Settery i Gettery w rzeczywistości to nic innego jak metody klasy (publiczne), dzięki którym możemy ustawiać wartość pola lub odczytywać jego wartość. Czyli mogą być przydatne – choć nasze pole będzie prywatne, to i tak dzięki np. Getterowi się do niego dostaniemy i odczytamy jego wartość. 😉

Klaska

Oczywiście do części pokazowej będziemy potrzebować jakieś prostej klasy: np. User.

 

public class User {
    private Long id;
    private String login;
    private String password;
    private String email;

    public User(Long id, String login, String password, String email) {
        this.id = id;
        this.login = login;
        this.password = password;
        this.email = email;
    }
}

Póki co wszystko powinno być zrozumiałe. 😉

Gettery

Zacznijmy od Getterów – tak jak wspomniałem są zwykłe metody w klasie.

Ich jedynym obowiązkiem jest zwracanie wartości konkretnego pola.

Dodatkowo wyróżnia ich przedrostek get – np. getLogin().

Pola w klasie User są private, sprawdźmy czy możemy odczytać ich wartość w main.:

public class Main {

    public static void main(String[] args) {
        User user = new User(1l, "admin", "admin", "admin@example.com");
        System.out.println("User id: " + user.id + ", user login: " + user.login);
    }
}

Jak widać, nie mamy dostepu do pól – co się zgadza, w końcu są one prywatne.

Jeżeli Twój kod się nie kompiluje zawsze zerknij w błędy jakie wypluwa kompilator – na ich podstawie spróbuj wywnioskować błąd lub poszukać o nim informacji w internecie.

Dodajmy, więc metody get dla wszystkich pól – tak jak wspomniałem będą one miały za zadanie zwracać wartość konkretnego pola klasy.

public class User {
    private Long id;
    private String login;
    private String password;
    private String email;

    public User(Long id, String login, String password, String email) {
        this.id = id;
        this.login = login;
        this.password = password;
        this.email = email;
    }

    public Long getId() {
        return id;
    }

    public String getLogin() {
        return login;
    }

    public String getPassword() {
        return password;
    }

    public String getEmail() {
        return email;
    }
}

Jak widzisz typ każdej metody jest odpowiednio dopasowany do typu pola – wiadomo, że skoro pole jest typu String to metoda, również musi zwracać String. 😉

Spróbujmy teraz dostać się do pól z poziomu main:

public class Main {

    public static void main(String[] args) {
        User user = new User(1l, "admin", "admin", "admin@example.com");
        System.out.println("User id: " + user.getId() + ", user login: " + user.getLogin());
    }
}

Kod się kompiluje, a wynik programu jest taki:

User id: 1, user login: admin

Jak widać wartości pól z obiektu user się zgadzają. Dotarliśmy do pól pomimo, że są prywatne – dzięki pośrednikowi, którym jest getter.

Settery

Skoro gettery zwracają nam wartość – to jeszcze potrzebujemy czegoś do ustawiania wartości – są to właśnie settery.

Dzięki setterom możemy zmieniać wartości pól – choćby były prywatne. Nic nie stoi na przeszkodzie. 😉

Zdefiniujmy sobie w klasie User settery dla wszystkich pól – oprócz ID, w końcu chcemy aby było unikalne dla każdego użytkownika!

public class User {
    private Long id;
    private String login;
    private String password;
    private String email;

    public User(Long id, String login, String password, String email) {
        this.id = id;
        this.login = login;
        this.password = password;
        this.email = email;
    }

    public Long getId() {
        return id;
    }

    public String getLogin() {
        return login;
    }

    public String getPassword() {
        return password;
    }

    public String getEmail() {
        return email;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

Teraz zmieńmy wszystkie możliwe pola i wyświetlmy ich wartości.

public class Main {

    public static void main(String[] args) {
        User user = new User(1l, "admin", "admin", "admin@example.com");
        System.out.println("User id: " + user.getId() + ", user login: " + user.getLogin() + ", user email: "+user.getEmail() + ", user password: "+user.getPassword());
        user.setLogin("nowy-admin");
        user.setPassword("admin-password");
        user.setEmail("updated-email@email.com");

        System.out.println("User id: " + user.getId() + ", user login: " + user.getLogin() + ", user email: "+user.getEmail() + ", user password: "+user.getPassword());
    }
}

I teraz po uruchomieniu programu:

User id: 1, user login: admin, user email: admin@example.com, user password: admin
User id: 1, user login: nowy-admin, user email: updated-email@email.com, user password: admin-password

Jak widać faktycznie wartości pól się zmieniły. 😉

Wszystko z głową…

O ile zazwyczaj stworzenie getterów dla wszystkich pól nie jest jeszcze samobójstwem – to stworzenie wszystkich setterów może być.

Tworząc wszystkie settery i gettery robimy to bezmyślnie – otrzymuje w końcu taką samą sytuację jakby nasze pola były publiczne – a nie prywatne. 😉

Dlatego jeżeli nasze pola nie są publiczne to setterów i getterów trzeba używać z głową – i samemu decydować jakie pole może się zmieniać (np. ID), a które nie. 😉

Podsumowując – starajmy się jak najbardziej zaostrzać dostęp do konkretnych pól i metod – aby były jak najmniej widocznie. Kiedyś zobaczysz tego zalety podczas pisania większego projektu. 😉

toString

Mówiłem Ci, że każdy obiekt ma w sobie kilka metod, kóre pochodzą z klasy Object.

Są one małą częścią naszej klasy i możemy tak naprawdę coś z tą częścią zrobić.

Mamy do dyspozycji metodę String toString() – która wyświetla informację o danym obiekcie. Domyślnie wyświetla ona nazwę i adres obiektu – czyli nic czytelnego dla użytkownika, lecz to nic możemy ją nadpisać – czyli przysłonić własną implementacją.

Postaraj się zdefiniować tą metodę w zadaniach, które są poniżej – wystarczy, że zdefiniujesz ją w ten sposób w swojej klasie:

public String toString() {
    return "Opis obiektu: to moje imie: " + name;
}

Zwróć uwagę, że zwraca ona String – więc, aby faktycznie wyświetlić informację o obiekcie w konsoli trzeba jeszcze użyć System.out.println – taka mała wskazówka. 😉

Podsumowanie

Temat lekcji raczej lekki i lekko rozszerzający poprzednią lekcję na temat modyfikatorów dostępu – czas na zadania, których zabrakło pod poprzednią lekcją. 😉

  1. Stwórz klasę Dog z prywatnymi polami: imię oraz rasa psa. Zastanów się, dla których stworzyć gettery i settery – myślę, że imię psa można jeszcze zmienić, lecz rasę… 😉 Dla klasy zdefiniuj także toString() – dzięki, której wyświetlisz informację o obiekcie w konsoli.
  2. Stwórz klasę Human z polami: imię, nazwisko oraz wiek, stwórz klasę SuperHero, która będzie dziedziczyć po Human z polem superPower. Wychodząc z założenia, że możemy zmienić tylko wiek człowieka i superbohatera napisz odpowiednie settery i gettery. Dla klas zdefiniuj także toString() – dzięki, której wyświetlisz informację o obiektach w konsoli.

Rozwiązania zadań możesz znaleźc tutaj.

Nie ma co cisnąć aż tak bardzo setterów i getterów bo chyba nie są, aż tak bardzo skomplikowanym zagadnieniem  – lepiej będzie poświęcić czas na ostatnie zagadnienie drugiego tygodnia – czyli tworzenia aplikacji. 😉