Gettery i settery w Javie

0

Chciałabym, aby ktoś na prostym przykładzie wytłumaczył mi o co chodzi z getterami i setterami w Javie, szukałam w google, na youtubie i w książce, "podstawy javy", swoją drogą dziwne że w książce nawet zdania o tym nie było.
Jedyne informacje jakie znajduje to teorie typu

"Gettery i settery to metody, które pozwalają odpowiednio pobierać i zapisywać wartość pól klasy."

Co nam w praktyce daje stosowanie takich metod ? Jak to zrozumieć ?

4

Jeśli np. masz klasę "kwadrat" to pewnie nie chcesz żeby jego bok miał ujemną długość, więc jeśli zamiast umożliwienia po prostu modyfikacji zmiennej "bok" zrobisz funkcję "setBok" to w tej funkcji możesz sprawdzać czy długość boku jest sensowna i jeśli nie to np. jakiś wyjątek rzucić.

1

Metody getter i setter bardziej ogólnie można nazwać mianem akcesorów. Pozwalają one zapewnić enkapsulację danego obiektu. Inaczej ujmując przechowujemy pola w ramach sekcji prywatnej bądź też chronionej natomiast dostęp do tych pól musimy zapewnić poprzez wykorzystanie tych metod getter i setter. Możemy tworzyć dostęp do pól do odczytu z wykorzystaniem metod get, lub/oraz do zapisu z wykorzystaniem metod set. Dzięki temu wyodrębniamy jakiś interfejs dostępu do danych, kolejną zaletę napisał kolega powyżej.

1

Poza tym, niektóre wartości obiektu mogą być np. automatycznie wyliczane na podstawie innych pol, wtedy raczej nie będziesz chciała udostępnić settera dla takiego pola.

Przykład:
Klasa kwadrat, będziesz chciała miec możliwość ustawienia długości pola a i b, jednak zamiast wprowadzić manualnie wartość pola tego kwadratu, raczej zadbasz o to, aby getPole() automatycznie je wyliczyło na podstawie podanych boków.

Czasem tez dany obiekt nie może istnieć bez jakiejś wartości, np Użytkownik bez loginu.
W takiej sytuacji powinnaś udostępnić konstruktor, w którym użytkownik będzie musiał podać login, sama metoda setLogin() może wtedy być pominięta.

0

A w takim typowo prostym programie gdzie wczytuję, wyświetlam imię i nazwisko:

public class firstHello {

	static Scanner wczytywarka = new Scanner(System.in);
	
	public static void main(String[] args) 
	{
		
		System.out.println("Podaj swoje imie: ");
		String imie = pobierzDane();
		System.out.println("Twoje imie to: " + imie);
		
		System.out.println("Podaj swoje nazwisko: ");
		String nazwisko = pobierzDane();
		System.out.println("Twoje nazwisko to: " + nazwisko);
	}

	public static String pobierzDane() 
	{
	    return wczytywarka.nextLine();
	}
	
}

Można na siłę użyć getterów i setterów ? Jakby to wyglądało ?
Moim zdaniem do takiego zadania nie jest to potrzebne, ale czytałam że trzeba od samego początku uczyć się tego używać nawet w miejscach które mogą się obyć bez tego.

1

@wioletta90 gettery i settery są związane z klasami/strukturami a twój program ma słowo class tylko dlatego że java wymaga żeby main() było w jakiejś klasie.
Wyobraź sobie że masz klasę

class Osoba{
    private final String imie;
    private final String nazwisko;
}

i to do takiego obiektu chcesz wczytać dane a potem je wypisać...

0

więc dodałam klasę Osoba, ale musiałam usunąć to

final
bo przecież imiona będą się zmieniały, a z tego co przeczytałam final oznacza że coś będzie niezmienne

przedstawia się to tak:

public class Osoba {

    private String imie;
    private String nazwisko;
	
    public String getImie() {
    	return imie;
    }
    
    public void setImie(String imie) {
    	this.imie = imie;
    }
    
    public String getNazwisko() {
    	return nazwisko;
    }
    
    public void setNazwisko(String nazwisko) {
    	this.nazwisko = nazwisko;
    }
    
    
    
	static Scanner wczytywarka = new Scanner(System.in);
	
	public static void main(String[] args) 
	{
		Osoba osobnik = new Osoba();
		
		System.out.println("Podaj swoje imie: ");
		osobnik.setImie(pobierzDane());
		
		
		System.out.println("Podaj swoje nazwisko: ");
		osobnik.setNazwisko(pobierzDane());
		
	}

	public static String pobierzDane() 
	{
	    return wczytywarka.nextLine();
	}
	
}

czy tak to się robi ?

3

Ano usuwanie tego finala to zły pomysł. Obiekty mutowalne są bardzo niewygodne i należy się ich wystrzegać jak ognia. Najwygodniej pracuje się z obiektami które nie mogą sie już zmienić po utworzeniu. Oczywiscie wtedy trzeba by zrobić jakieś

new Osoba(wczytajDane(), wczytajDane());

Poza tym ta "wczytywarka" powinna być zmienną w funkcji main() a nie statycznym polem klasy. W ogóle klasa z main() raczej nie powinna mieć żadnych pól.

0
  1. Rozumiem, że obiekty mutowalne to takie które się zmieniają, ale
private final String imie;

to pole a nie obiekt ?

  1. Takie rzeczy jak imię, nazwisko w programach raczej będę się zmieniały, a
final

chyba to zablokuje i będzie jedno stałe imię/nazwisko ?

  1. Tego nie rozumiem od poczatku do końca:

Oczywiscie wtedy trzeba by zrobić jakieś

new Osoba(wczytajDane(), wczytajDane());
  1. Gdy usunęłam static i przeniosłam
Scanner wczytywarka = new Scanner(System.in);

do metody main() z klasy, to w metodzie pobierzDane() podkreśliło mi "wczytywarka" i wyświetliło bład "wczytywarka cannot be resolved", jak sobie z tym poradzić ?

W ogóle klasa z main() raczej nie powinna mieć żadnych pól.

Chodzi o metodę main() ? Jeżeli nie, to co to jest klasa z main() ? Tak jak mówi nazwa? Klasa w której jest metoda(main) ? W sumie jeszcze nie widziałam programu z dwiema klasami.

0

Klasa z main() to jakas klasa testowa. Np.:
public class JakasKlasaTestowa{
//tutaj nie ma pol zadnych
public static void main(String[] args){
...

2

@wioletta90 obiekty mutowalne to takie które mogą zmieniać swój stan, a stan obiektu zwykle określają jego pola właśnie. Nie odróżniasz OBIEKTU od KLASY. Klasą jest np. Krzesło a obiektem może być krzesło na którym teraz siedzisz i krzesła które masz w kuchni. Widzisz różnicę? Polem klasy może być materiał z którego wykonane jest krzesło, a każde z twoich krzeseł może być wykonane z innego materiału. Ten materiał zapewne jest "niezmienny" tzn drewniane krzesło nagle nie stanie sie metalowe. Więc jak widzisz niezmienność/niemutowalność nijak nie sprawia że nie możesz mieć różnych krzeseł. Tak samo jest z Osobami. Osoba raczej nie zmieni nagle swojego imienia i nazwiska ;]
Ten scanner musisz sobie teraz do tej metody przekazać jako parametr. Dużo łatwiej analizuje się kod kiedy metody/funkcje dostają w parametrach obiekty z którymi mają pracować.
Nie, nie chodzi mi o metodę main. Chodzi mi o klasę w której masz main(). Ta klasa powinna zawierać tylko tego maina i nic więcej.

2

Ale kombinujecie. @wioletta90 pyta o tak podstawowe rzeczy jak akcesory, dopiero zaczyna się uczyć OOP a @Shalom z mutowalnością wyskakuje.

@wioletta90 jak najbardziej usuń final i korzystaj z akcesorów żeby zmieniać wartości obiektu. Na bardziej skomplikowane zagadnienia przyjdzie jeszcze czas. Ważne żebyś zrozumiała sens używania akcesorów.

0

a więc stworzyłam klasę main w której jest sama metoda main() i mój program wygląda następująco:

package pl.wioletta.hello;

import java.util.Scanner;

public class Osoba {

    private final String imie;
    private final String nazwisko;
	
    public String getImie() {
    	return imie;
    }
    
    public void setImie(String imie) {
    	this.imie = imie;
    }
    
    public String getNazwisko() {
    	return nazwisko;
    }
    
    public void setNazwisko(String nazwisko) {
    	this.nazwisko = nazwisko;
    }
    
    
    
    public class KlasaZMain {
    	   	 
	
	public static void main(String[] args) 
	{
		Scanner wczytywarka = new Scanner(System.in);
		
		Osoba osobnik = new Osoba();
		
		System.out.println("Podaj swoje imie: ");
		osobnik.setImie(pobierzDane());
		
		
		System.out.println("Podaj swoje nazwisko: ");
		osobnik.setNazwisko(pobierzDane());
		
	}

    }	
	
	
	public static String pobierzDane() 
	{
	    return wczytywarka.nextLine();
	}
	
}

teraz mówisz, że muszę przekazać skanner do metody jako parametr, ale do której metody ? pobierz Dane() ? tam już chyba jest

1
  1. To się teraz nie skompiluje bo dla zmiennych final nie możesz mieć settera ;]

tam już chyba jest

O RLY? String pobierzDane() ja tu widzę puste nawiasy w nagłowki metody, więc chyba jednak parametrów nie ma...

0
  1. jak setterów być nie może, to w sumie gettery też nie są potrzebne ?
  2. Pierwszy raz to robie ale chyba dobrze:
	public static String pobierzDane(Scanner wczytywarka) 
	{
	    return wczytywarka.nextLine();
	}
1

Gettery i settery generalnie są uważane za nieładne przy obiektach domenowych bo łamią enkapsulacje, niemniej czasem trudno ich uniknąć. Wyobraź sobie że masz teraz listę List<Osoba> w programie i chcesz wybrać z tej listy tylko osoby z nazwiskiem na jakaś literkę, albo o danym imieniu. Jak zrobisz to bez gettera? ;)

0

a więc usunęłam settery i przekazałam odpowiednie parametry do metody pobierzDane(), teraz nie wiem jak bez setterów pobrać dane od użytkownika, wcześniej miałam

osobnik.setImie(pobierzDane());
, czyli wywoływałam metode dla obiektu osobnik z parametrem pobierzDane() [pokazuje jak myślę, jak źle to dajcie znać]

proponuję zrobić wczytywanie dla imienia taką linijką kodu:

String imie = wczytywarka.nextLine();

to co aktualnie mam:

package pl.wioletta.hello;

import java.util.Scanner;

public class Osoba {

    private final String imie;
    private final String nazwisko;
	
    public String getImie() {
    	return imie;
    }
    
    
    public String getNazwisko() {
    	return nazwisko;
    }
    
        
    public class KlasaZMain {
    	   	 
	
	public static void main(String[] args) 
	{
		Scanner wczytywarka = new Scanner(System.in);
		
		Osoba osobnik = new Osoba();
		
		System.out.println("Podaj swoje imie: ");

		
		
		System.out.println("Podaj swoje nazwisko: ");

		
	}

    }	
	
	
	public static String pobierzDane(Scanner wczytywarka) 
	{
	    return wczytywarka.nextLine();
	}
	
}
0

zadam pytanie przy temacie: czy settery na DTO są okey ?

0

Settery na DTO sugerują że możesz przypadkiem trafić na obiekty które nie są do końca zainicjalizowane albo są niespójne. (a piewcy DDD w ogóle powiedzą że DTO to zło ;) )

0

@Shalom okey czyli załóżmy jeżeli mam:

dao (model) -> service (pluje immutable DTOsami) -> JSFowy controller widoku

to teraz w tym controlerze pobieram sobie z serwisu np. List<AccountDto> accountList i tak to mogłabym trzymać tą listę w polu w klasie kontrolera jako private List<AccountDto>
i np w takim datatable się iterować i mieć na wierszu np. input texta z value="#{acc.name}" itd... AccountDto ma settery i na końcu wołam jedynie service.update(accountList).

a tak to jak AccountDto jest immutable i nie mam setterow to co wtedy? muszę zrobić specjalnie kolejną klasę tym razem muttable opakowującą AccountDto dla jsfowego kontrolera?
interesuje mnie ten konretny przypadek z datatable.

Nie mówię, że ta dodatkowa klasa to źle tylko pytam z niewiedzy i zastanawiam się na jakim etapie złamanie tych zasad ma sens i przy jakiej skali wielkości projektu
przestrzeganie tych wszystkich zasad daje więcej czasu i fajności niż zabiera.

1

Mam nadzieje że to co nazwałaś "controller widoku" i w którym to chcesz mieć pola, to jest Managed Bean, bo inaczej to jest jakiś WTF.
To jest oczywiście szczególny przypadek kiedy robisz input beana do którego chcesz wpakować dane z Widoku, bo wtedy technologia może na tobie wymusić posiadanie bezparametrowego kontruktora i setterów (zgodnie z konwencja JavaBeans). I o ile tylko tam w sposób niejawny te settery są użyte to ok.
Analogiczny problem może występować np. dla klas @Entity ale to jest zupełnie inna bajka kiedy mówimy o czymś co wymusza na tobie użyta technologia.

0

Tak tak managed bean. Okey czyli jednak pewnych rzeczy nie przeskoczę.

0

siedzę przy tym już długo i nic nie wymyśliłam,

liczę na jakąś podpowiedź

new Osoba(wczytajDane(), wczytajDane());
0

w kodzie mam

Osoba osobnik = new Osoba();

czyli niby teraz do konstruktora mam przekazać jako parametr 2 takie same metod wczytajDane(), ale po co ? Chciałam,aby program wczytał imię po linijce

System.out.println("Podaj swoje imie: ");

więc skąd program będzie wiedział o co chodzi ?

4

Jejku, no to wczytaj o_O

System.out.println("Podaj swoje imie: ");
String imie = wczytajDane(scanner);
System.out.println("Podaj swoje nazwisko: ");
String nazwisko = wczytajDane(scanner);

Osoba osoba = new Osoba(imie, nazwisko);

Zaraz muszę gdzieś poszukać chyba ten link z pracą jako pomocnik piekarza...

4

OK, nie śledziłam całego wątku, ale właściwie czemu nie zrobisz:

public static void main(String[] args) 
    {
        Scanner wczytywarka = new Scanner(System.in);
 
        System.out.println("Podaj swoje imie: ");
 	String imie = wczytajDane(scanner);
 
        System.out.println("Podaj swoje nazwisko: ");
 	String nazwisko = wczytajDane(scanner);

	//teraz masz juz imię i nazwisko, więc tworzysz obiekt
	Osoba osobnik = new Osoba(imie, nazwisko);
 
    }
4

Wydaje mi się, że zbytnio kombinujesz. Nie programuj na ślepo permutacjami tylko poczytaj solidnie o podstawach i pomyśl jak to wykombinować i prawidłowo zrobić.
Nie tak byle działało tylko pomyśl tak jak komputer. Popatrz czemu nie zrobisz w taki sposób:

System.out.println("Podaj swoje imie: ");
final String imie = wczytajDane(scanner);
System.out.println("Podaj swoje nazwisko: ");
final String nazwisko = wczytajDane(scanner);

final Osoba obiektOsoba = new Osoba(imie, nazwisko);

oczywiście wbij to do bloku public static void main(String[] args) { ;]

EDIT: poproszę o plusa

0

a nie można najpierw stworzyć obiekt ?

Kilka rzeczy mam podkreślonych, chociażby parametr imie i nazwisko przy tworzeniu obiektu, tak to wygląda u mnie:

package pl.wioletta.hello;

import java.util.Scanner;

public class Osoba {

    private final String imie;
    private final String nazwisko;
	
    public String getImie() {
    	return imie;
    }
    
    
    public String getNazwisko() {
    	return nazwisko;
    }
    
        
    public class KlasaZMain {
    	   	 
	
	public static void main(String[] args) 
	{
		Scanner wczytywarka = new Scanner(System.in);
						
				
		System.out.println("Podaj swoje imie: ");
		String imie = wczytajDane(Scanner);
		
		
		System.out.println("Podaj swoje nazwisko: ");
		String nazwisko = wczytajDane(Scanner);
		
		Osoba osobnik = new Osoba(imie, nazwisko);
	}

    }	
	
	
	public static String pobierzDane(Scanner wczytywarka) 
	{
	    return wczytywarka.nextLine();
	}
	
}
1

W klasie Osoba brakuje Ci konstruktora, który przyjmie te dwa parametry.

1 użytkowników online, w tym zalogowanych: 0, gości: 1