W miejscu pracy widzę wiele klas, które wykonują takie rzeczy:
public class ClassThatCallsItsOwnGettersAndSetters {
private String field;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public void methodWithLogic() {
setField("value");
//do stuff
String localField = getField();
//do stuff with "localField"
}
}
Gdybym napisał to od zera, methodWithLogic()
zamiast tego napisałbym tak:
public class ClassThatUsesItsOwnFields {
private String field;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public void methodWithLogic() {
field = "value";
//do stuff
//do stuff with "field"
}
}
Wydaje mi się, że kiedy klasa wywołuje własne metody pobierające i ustawiające, utrudnia to odczytanie kodu. Dla mnie prawie implikuje to, że w tym wywołaniu metody dzieje się złożona logika, nawet w naszym przypadku prawie nigdy tak nie jest. Kiedy debuguję jakiś nieznany kod, kto może powiedzieć, że błąd nie jest efektem ubocznym tej metody? Innymi słowy, sprawia, że biorę wiele dodatkowych podróży w podróż po zrozumieniu kodu.
Czy są zalety pierwszej metody? Czy pierwsza metoda jest rzeczywiście lepsza?
java
object-oriented
programming-practices
Daniel Kaplan
źródło
źródło
Odpowiedzi:
Nie powiem, co jest lepsze lub gorsze, ponieważ częściowo zależy to od twojej sytuacji (moim zdaniem). Ale weź pod uwagę, że twoje programy pobierające i ustawiające mogą później zmienić implementację, a ominięcie ich pominie tę logikę.
Na przykład, co się stanie, jeśli dodasz „brudną” flagę do niektórych pól setera? Dzwoniąc do seterów w kodzie wewnętrznym, ustawisz brudną flagę bez zmiany innego kodu. W wielu sytuacjach byłoby to dobre.
źródło
setField()
od początku, właśnie wprowadziłeś błąd.Bezpośrednie wywołanie setera nie jest samo w sobie problemem. Pytanie powinno naprawdę brzmieć: Dlaczego nasz kod ma wszędzie setery?
Zmienne klasy są niebezpieczną grą, szczególnie tam, gdzie sama klasa zarządza własnym stanem. Zastanów się, ilu z tych seterów naprawdę musi istnieć. Ile można ustawić w konstruktorze, a następnie całkowicie zamknąć je sama klasa?
Jeśli pole musi być ustawiane zewnętrznie, zadaj sobie pytanie, czy powinna istnieć metoda z logiką. Czy sama klasa jest tak naprawdę klasą danych / stanu? Czy ta klasa ma więcej niż jedną odpowiedzialność?
Nie zrozum mnie źle, będą przypadki, w których będzie to w porządku. Nie mówię, że powinieneś całkowicie wyeliminować seterów na klasach z logiką. Ale powinny to być wyjątki, a nie reguła. I w tych kilku przypadkach powinno być oczywiste, do którego dostępu należy uzyskać bezpośredni dostęp.
źródło
Tak, metody twojej klasy powinny wywoływać osoby pobierające i ustawiające. Chodzi przede wszystkim o pisanie getterów i setterów na przyszłość. Możesz uczynić każdą właściwość polem i bezpośrednio ujawniać dane użytkownikom klasy. Powodem, dla którego budujesz programy pobierające i ustawiające, niekoniecznie jest to, że istnieje teraz złożona logika, ale aby interfejs nie zepsuł się w przyszłości, jeśli będziesz musiał go dodać.
źródło
someField=newValue; refresh();
Jeśli metoda pozwala ustawić wiele pól, wywołanie ustawiaczy w celu zapisania tych pól spowodowałoby zbędne operacje „odświeżania”. Zapisanie wszystkich pól, a następnierefresh()
jednorazowe wywołanie, może zapewnić bardziej wydajną i gładszą operację.Aby odpowiedzieć na twoje pytania jednym słowem, tak.
Posiadanie klasy wywołującej własne moduły pobierające i ustawiające dodaje rozszerzalności i stanowi lepszą bazę dla przyszłego kodu.
Powiedz, że masz coś takiego:
Wywoływanie seterów na rok i wykonanie obecnie mogą nie dodawać żadnej funkcjonalności, ale co, jeśli chcesz dodać coś takiego jak sprawdzanie poprawności danych wejściowych do seterów?
źródło
Jedną z rzeczy, o których nie wspomniano, jest to, że getter i settery (jak wszystkie metody) są wirtualne w Javie. Dodaje to kolejną funkcję do zawsze używania ich w kodzie. Inny użytkownik może rozszerzyć twoją klasę, nadpisując twoje pobierające i ustawiające. Klasa podstawowa używałaby wtedy danych podklasy zamiast własnych. W języku, w którym wyraźnie zaznaczasz funkcje wirtualne, jest to o wiele wygodniejsze, ponieważ możesz przewidzieć i zadeklarować, za pomocą których funkcji można to zrobić. W Javie jest to coś, o czym zawsze musisz wiedzieć. Jeśli jest to pożądane zachowanie, użycie ich w kodzie jest dobrą rzeczą, w przeciwnym razie nie tak bardzo.
źródło
Jeśli próbujesz osiągnąć coś, co zapewnia interfejs publiczny, użyj getters / setters.
Jednak jako właściciel / programista klasy masz dostęp do prywatnych sekcji swojego kodu (oczywiście z klasy), ale jesteś również odpowiedzialny za złagodzenie niebezpieczeństw.
Więc może masz moduł pobierający, który iteruje po wewnętrznej liście i chcesz uzyskać bieżącą wartość bez zwiększania iteratora. W takim przypadku użyj zmiennej prywatnej.
źródło
Tak. Gettery i settery reprezentują stan, więc odwróć to pytanie - czy chcesz śledzić wiele sposobów zmiany stanu obiektów w ten sam sposób, chyba że musisz?
Im mniej rzeczy musisz śledzić, tym lepiej - dlatego łatwiej jest sobie poradzić z obiektami niezmiennymi.
Zastanów się, nic nie stoi na przeszkodzie, abyś miał zarówno pole publiczne, jak i publiczny getter / setter - ale co byś zyskał?
Czasami może być pożądane, a nawet konieczne, aby uzyskać bezpośredni dostęp do pola z jednego lub więcej powodów, nie powinieneś się tego unikać, jeśli tak się stanie. Ale tak naprawdę powinieneś to zrobić tylko wtedy, gdy jest to określone korzyści.
źródło
Obie metody mają swoje przypadki użycia. Ponieważ obiekt ustawiający publicznie utrzymuje spójność wartości pola (i / lub wartości powiązanych), należy używać narzędzia ustawiającego, gdy logika metody nie zakłóca tej logiki spójności. Jeśli po prostu ustawisz swoją „właściwość”, użyj setera. Z drugiej strony zdarzają się sytuacje, w których potrzebny jest bezpośredni dostęp do niektórych pól, na przykład operacje zbiorcze z ciężkim setera lub operacje, w których koncepcja setera jest zbyt prosta.
Twoim obowiązkiem jest utrzymanie spójności. Setter robi to z definicji, ale nie może obejmować skomplikowanych przypadków.
źródło
Powiedziałbym, że nie ..
Jeśli twoje programy pobierające / ustawiające po prostu pobierają i ustawiają (bez leniwej inicjalizacji, bez sprawdzania itp.), Po prostu używaj zmiennych. Jeśli w przyszłości zmienisz swoje metody pobierające / ustawiające, możesz bardzo dobrze zmienić swoją
methodWithLogic()
(ponieważ zmienia się Twoja klasa) i możesz zadzwonić do metody pobierającej / ustawiającej zamiast bezpośredniego przypisania. Możesz udokumentować to wywołanie dla gettera / settera (ponieważ dziwne będzie wywoływanie gettera / settera, gdy reszta kodu twojej klasy bezpośrednio używa zmiennej).JVM będzie wykonywać częste połączenia do osób pobierających / ustawiających. Tak więc nigdy nie jest to problem z wydajnością. Korzyści ze stosowania zmiennych to czytelność i IMHO, wybrałbym to.
Mam nadzieję że to pomoże..
źródło