Czy to dobry, czy zły pomysł, aby setery w javie zwracały „to”?
public Employee setName(String name){
this.name = name;
return this;
}
Ten wzorzec może być przydatny, ponieważ wtedy możesz ustawić łańcuchy ustawiające w następujący sposób:
list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));
zamiast tego:
Employee e = new Employee();
e.setName("Jack Sparrow");
...and so on...
list.add(e);
... ale to w pewien sposób jest sprzeczne ze standardową konwencją Podejrzewam, że to może być opłacalne tylko dlatego, że może sprawić, że Seter zrobi coś innego pożytecznego. Widziałem, że ten wzorzec wykorzystywał niektóre miejsca (np. JMock, JPA), ale wydaje się rzadki i ogólnie używany tylko w przypadku bardzo dobrze zdefiniowanych interfejsów API, w których ten wzorzec jest używany wszędzie.
Aktualizacja:
To, co opisałem, jest oczywiście ważne, ale tak naprawdę szukam kilku przemyśleń na temat tego, czy jest to ogólnie akceptowalne i czy są jakieś pułapki lub powiązane najlepsze praktyki. Wiem o wzorcu Konstruktora, ale jest on nieco bardziej zaangażowany niż to, co opisuję - jak opisuje to Josh Bloch, istnieje powiązana statyczna klasa Konstruktora do tworzenia obiektów.
źródło
this
. Czasami nawet zmieniam funkcję, aby zamiast zwracać wartość, działa ona na elemencie obiektu, tylko po to, aby to zrobić. To jest wspaniałe. :)Odpowiedzi:
Nie sądzę, żeby było w tym coś szczególnie złego, to tylko kwestia stylu. Przydaje się, gdy:
Alternatywami dla tej metody mogą być:
Jeśli zamierzasz ustawić tylko kilka właściwości naraz, powiedziałbym, że nie warto zwracać „tego”. Z pewnością spada, jeśli później zdecydujesz się zwrócić coś innego, na przykład wskaźnik / komunikat o stanie / sukcesie.
źródło
To nie jest zła praktyka. To coraz bardziej powszechna praktyka. Większość języków nie wymaga, abyś zajmował się zwróconym obiektem, jeśli nie chcesz, więc nie zmienia on „normalnej” składni użycia settera, ale pozwala na łączenie seterów razem.
Jest to powszechnie nazywane wzorcem konstruktora lub płynnym interfejsem .
Jest to również powszechne w API Java:
źródło
bla.foo.setBar1(...) ; bla.foo.setBar2(...)
kiedy można napisaćbla.foo /* newline indented */.setBar1(...) /* underneath previous setter */ .setBar2(...)
(nie można używać linebreaks w komentarzu tak podobny do tego :-( ... nadzieję, że rozważa się punkt 10 takich ustawiające lub bardziej złożone połączenia)Podsumowując:
Kilka innych punktów nie wymienionych:
Narusza to zasadę, że każda funkcja powinna wykonać jedną (i tylko jedną) rzecz. Możesz w to wierzyć lub nie, ale w Javie uważam, że działa dobrze.
IDE nie wygenerują ich dla Ciebie (domyślnie).
I w końcu oto punkt danych w świecie rzeczywistym. Mam problemy z użyciem biblioteki zbudowanej w ten sposób. Konstruktor zapytań Hibernacja jest tego przykładem w istniejącej bibliotece. Ponieważ metody zestawu * zapytania zwracają zapytania, nie można powiedzieć, patrząc tylko na podpis, jak z niego korzystać. Na przykład:
Wprowadza niejednoznaczność: czy metoda modyfikuje bieżący obiekt (twój wzorzec), czy może Query jest naprawdę niezmienny (bardzo popularny i cenny wzorzec), a metoda zwraca nowy. Utrudnia to korzystanie z biblioteki, a wielu programistów nie wykorzystuje tej funkcji. Gdyby setery były seterami, łatwiej byłoby z niego korzystać.
źródło
this
to mało złożona nauka o rakietach. :-)Wolę używać do tego metod „z”:
A zatem:
Ostrzeżenie : ta
withX
składnia jest powszechnie używana do zapewnienia „ustawiaczy” dla niezmiennych obiektów, więc osoby wywołujące te metody mogą oczekiwać, że utworzą nowe obiekty, a nie zmutują istniejącą instancję. Może bardziej rozsądnym sformułowaniem byłoby coś takiego:Dzięki konwencji nazewnictwa chainsetXyz () praktycznie wszyscy powinni być zadowoleni.
źródło
get
Aset
i Awith
dla każdej klasy. Jednak wciąż jest to interesujące rozwiązanie. :)Project Lombok
„s@Getter/@Setter
adnotacji ... że byłoby fantastyczne łańcuchowym. Możesz też użyć czegoś takiego jakKestrel
kombinator ( github.com/raganwald/Katy ), którego używają znajomi JQuery i Javascript.with
prefiks jest inna konwencja. ponieważ @ qualidafial podał przykład. metody z prefiksemwith
nie powinny zwracać,this
ale raczej nowe wystąpienie, takie jak bieżące, alewith
ta zmiana. Robi się to, gdy chcesz, aby twoje obiekty były niezmienne. Kiedy więc widzę metodę z prefiksemwith
, zakładam, że otrzymam nowy obiekt, a nie ten sam obiekt.Jeśli nie chcesz wracać
'this'
z programu ustawiającego, ale nie chcesz używać drugiej opcji, możesz użyć następującej składni, aby ustawić właściwości:Nawiasem mówiąc, myślę, że jest nieco czystszy w C #:
źródło
equals
metodę. Istnieją bardzo czyste sposoby radzenia sobie z anonimowymi zajęciami,equals
jeśli wiesz, co robisz.Nie tylko łamie konwencję getters / setters, ale także łamie ramy referencyjne metod Java 8.
MyClass::setMyValue
jestBiConsumer<MyClass,MyValue>
imyInstance::setMyValue
jestConsumer<MyValue>
. Jeśli masz zwrot seterathis
, to nie jest on już prawidłową instancjąConsumer<MyValue>
, a raczej aFunction<MyValue,MyClass>
, i spowoduje, że cokolwiek przy użyciu odwołań do metod do tych seterów (zakładając, że są to nieważne metody) ulegnie awarii.źródło
Consumer<A>
iFunction<A,B>
domyślną implementacjęvoid accept(A a) { apply(a); }
. Następnie można go łatwo użyć jako jednego z nich i nie złamie żadnego kodu wymagającego określonej formy.Nie znam Java, ale zrobiłem to w C ++. Inni twierdzą, że sprawia, że linie są naprawdę długie i bardzo trudne do odczytania, ale robiłem to tak wiele razy:
To jest jeszcze lepsze:
przynajmniej tak mi się wydaje. Ale możesz głosować za mną i nazwać mnie okropnym programistą, jeśli chcesz. I nie wiem, czy wolno ci to robić w Javie.
źródło
//
po każdej metodzie, jeśli skonfigurujesz IDE, aby nie dołączało już zawiniętych linii (np. Eclipse> Właściwości> Java> Styl kodu> Formatyzator> Zawijanie linii> Nigdy nie dołączaj do już zawiniętych linii).Ten schemat (zamierzony gra słów), zwany „płynnym interfejsem”, staje się obecnie dość popularny. Jest do przyjęcia, ale tak naprawdę to nie jest moja filiżanka herbaty.
źródło
Ponieważ nie zwraca nieważności, nie jest już prawidłowym narzędziem do ustawiania właściwości JavaBean. Może to mieć znaczenie, jeśli jesteś jedną z siedmiu osób na świecie korzystających z wizualnych narzędzi „Bean Builder” lub jedną z 17 osób korzystających z elementów JSP-bean-setProperty.
źródło
Przynajmniej teoretycznie może uszkodzić mechanizmy optymalizacji JVM poprzez ustawienie fałszywych zależności między wywołaniami.
Ma to być cukier składniowy, ale w rzeczywistości może powodować skutki uboczne w super-inteligentnej maszynie wirtualnej Java 43.
Dlatego głosuję nie, nie używaj go.
źródło
set
metody zależy od pierwszejset
metody, chociaż jest znany programistom.-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining
Jva7 jdk zdecydowanie inline łączy łańcuchowe metody i wykonuje tę samą liczbę iteracji, których potrzeba, aby oznaczyć seterów pustki jako gorące i również je wstawić. Uważa, że nie doceniasz mocy algorytmów przycinania kodu operacji JVM; jeśli wie, że to zwracasz, pominie kod op-jrs (instrukcja powrotu java) i pozostawi to na stosie.To wcale nie jest zła praktyka. Ale nie jest kompatybilny ze specyfikacją JavaBeans Spec .
I wiele specyfikacji zależy od tych standardowych akcesoriów.
Zawsze możesz sprawić, że będą ze sobą współistnieć.
Teraz możemy ich używać razem.
Oto kolejna wersja dla niezmiennego obiektu.
Teraz możemy to zrobić.
źródło
some
pola. Po drugie, powinieneś dodać zabezpieczenie i ustawićsome
nanull
build (), abySome
było naprawdę niezmienne, w przeciwnym razie możesz ponownie wywołaćbuilder.value()
tę samą instancję Konstruktora. I wreszcie, tak, masz konstruktora, aleSome
nadal masz konstruktor publiczny, co oznacza, że otwarcie nie popierasz korzystania z konstruktora, tzn. Użytkownik nie wie o tym inaczej niż wypróbowanie lub wyszukanie metody ustawiania niestandardowegovalue
w ogóle.Jeśli zastosujesz tę samą konwencję w całej aplikacji, wydaje się to w porządku.
Z drugiej strony, jeśli istniejąca część twojej aplikacji korzysta ze standardowej konwencji, trzymałbym się jej i dodawałbym konstruktorów do bardziej skomplikowanych klas
źródło
Paulo Abrantes oferuje inny sposób na płynne ustawianie JavaBean: zdefiniowanie wewnętrznej klasy konstruktora dla każdego JavaBean. Jeśli używasz narzędzi, które są flummoxowane przez seterów zwracających wartości, wzorzec Paulo może pomóc.
źródło
Jestem zwolennikiem seterów, którzy zwracają „to”. Nie obchodzi mnie, czy to nie jest zgodne z fasolą. Według mnie, jeśli wyrażenie / instrukcja „=” jest w porządku, to setery zwracające wartości są w porządku.
źródło
Kiedyś wolałem takie podejście, ale zdecydowałem się go nie stosować.
Powody:
Wzorzec budowniczego, który widziałem, nie używa konwencji setFoo (foo) .setBar (bar), ale więcej foo (foo) .bar (bar). Być może właśnie z tych powodów.
Jest to, jak zawsze, kwestia gustu. Po prostu lubię podejście „najmniej niespodzianek”.
źródło
Ten szczególny wzór nazywa się Łączeniem metod. Link do Wikipedii , zawiera więcej wyjaśnień i przykładów tego, jak odbywa się to w różnych językach programowania.
PS: Właśnie pomyślałem o pozostawieniu go tutaj, ponieważ szukałem konkretnej nazwy.
źródło
Na pierwszy rzut oka: „Upiorne!”.
Po dalszych przemyśleniach
jest w rzeczywistości mniej podatny na błędy niż
To bardzo interesujące. Dodawanie pomysłu do torby na narzędzia ...
źródło
list
na początku nie ma zbędnych .Tak, myślę, że to dobry pomysł.
Gdybym mógł coś dodać, co z tym problemem:
To zadziała:
To nie zostanie zaakceptowane przez Eclipse! :
Wynika to z faktu, że setName () zwraca People, a nie Friend, i nie ma PeoplesetNickName.
Jak moglibyśmy napisać settery zwracające klasę SELF zamiast nazwy klasy?
Coś takiego byłoby w porządku (jeśli istniałoby słowo kluczowe SELF). Czy to w ogóle istnieje?
źródło
class C<S extends C<S>>
, co jest bezpieczniejsze niż zwykłyS extends C
. a) w przypadkuA extends B
, iB extends C<B>
, i masz a, trzeba tylko wiedzieć, że Zwracane jest B, chyba że A zastępuje każdą metodę. b) Nie możesz oznaczać lokalnego, nie-surowegoC<C<C<C<C<...>>>>>
.Zasadniczo jest to dobra praktyka, ale może być konieczne, aby funkcje typu set używały typu Boolean w celu ustalenia, czy operacja zakończyła się powodzeniem, czy nie, to też jest jeden sposób. Ogólnie rzecz biorąc, nie ma dogmatu, aby powiedzieć, że to jest dobre łóżko lub łóżko, to oczywiście pochodzi z sytuacji.
źródło
Z oświadczenia
widzę dwie rzeczy
1) Stwierdzenie bez znaczenia. 2) Brak czytelności.
źródło
Może to być mniej czytelne
albo to
Jest to o wiele bardziej czytelne niż:
źródło
Tworzę moje setery już od dłuższego czasu i jedynym prawdziwym problemem są biblioteki, które trzymają się ścisłego getPropertyDescriptors, aby uzyskać dostęp do czytnika / zapisu komponentu bean. W takich przypadkach java „bean” nie będzie mieć pisarzy, których można by oczekiwać.
Na przykład, nie przetestowałem tego na pewno, ale nie zdziwiłbym się, że Jackson nie rozpoznaje tych ustawników podczas tworzenia obiektów Java z json / map. Mam nadzieję, że się mylę w tej sprawie (wkrótce ją przetestuję).
W rzeczywistości rozwijam lekki ORM zorientowany na SQL i muszę dodać trochę kodu przed getPropertyDescriptors do rozpoznawanych ustawiaczy, które to zwracają.
źródło
Dawno temu odpowiedz, ale moje dwa centy ... W porządku. Chciałbym, żeby ten płynny interfejs był używany częściej.
Powtórzenie zmiennej „fabrycznej” nie dodaje więcej informacji poniżej:
To jest czystsze, imho:
Oczywiście, jako jedna z już wspomnianych odpowiedzi, interfejs API Java musiałby zostać dostosowany, aby zrobić to poprawnie w niektórych sytuacjach, takich jak dziedziczenie i narzędzia.
źródło
Lepiej jest używać innych konstrukcji języka, jeśli są dostępne. Na przykład w Kotlin korzystałbyś z , aplikował lub pozwalał . Jeśli używasz tego podejścia, tak naprawdę nie będziesz musiał zwracać instancji od settera.
Takie podejście pozwala na kod klienta:
Oto kilka przykładów.
źródło
Gdy piszę API, używam „return this”, aby ustawić wartości, które zostaną ustawione tylko raz. Jeśli mam inne wartości, które użytkownik powinien móc zmienić, zamiast tego używam standardowego selektora pustek.
Jednak tak naprawdę jest to kwestia preferencji, a moim zdaniem setery łańcuchowe wyglądają całkiem fajnie.
źródło
Zgadzam się ze wszystkimi plakatami, które twierdzą, że łamie to specyfikację JavaBeans. Są powody, aby to zachować, ale uważam również, że zastosowanie wzorca budowniczego (do którego nawiązywano) ma swoje miejsce; tak długo, jak nie jest wszędzie stosowany, powinno być dopuszczalne. „It's Place” jest dla mnie miejscem, w którym punktem końcowym jest wywołanie metody „build ()”.
Istnieją oczywiście inne sposoby ustawiania tych wszystkich rzeczy, ale zaletą jest to, że unika 1) wieloparametrowych publicznych konstruktorów i 2) częściowo określonych obiektów. Tutaj masz konstruktora, który zbiera to, co jest potrzebne, a następnie wywołuje na końcu jego „build ()”, co może zapewnić, że częściowo określony obiekt nie zostanie skonstruowany, ponieważ ta operacja może mieć mniej niż publiczną widoczność. Alternatywą byłyby „obiekty parametrów”, ale to IMHO popycha problem o jeden poziom wstecz.
Nie lubię konstruktorów wieloparametrowych, ponieważ zwiększają prawdopodobieństwo przekazania wielu argumentów tego samego typu, co może ułatwić przekazanie niewłaściwych argumentów do parametrów. Nie lubię używać wielu ustawień, ponieważ obiekt może być używany, zanim zostanie w pełni skonfigurowany. Ponadto pojęcie posiadania wartości domyślnych w oparciu o poprzednie wybory jest lepiej obsługiwane w metodzie „build ()”.
Krótko mówiąc, uważam, że jest to dobra praktyka, jeśli jest właściwie stosowana.
źródło
Zły nawyk: Seter ustaw getter get
co z jawnym zadeklarowaniem metody, która robi to dla U
źródło