* Czy URL to twoja klasa, czy biblioteczna?
* Czy w ifach chodzi o to, �e item jest url'em w postaci obiektu URL
albo w postaci Stringa?
* Jakiej klasy/interfejsu jest item?
pozdr,
mb
W dniu 2011-07-06 21:59, Jacek Laskowski pisze:
> Cze��,
>
> W�a�nie trafi�em na poni�szy kawa�ek kodu i przyku� moj� uwag�, bo w
> zasadzie "zmusi�" mnie, aby go zamieni� na rozwi�zanie z metodami
> przeci��onymi.
>
> Ten kawa�ek kodu:
>
> if (item instanceof URL) {
> ...
> } else if (item instanceof String) {
> ...
> } else...
>
> zamieni�bym na:
>
> void doSth(URL url)
> void doSth(String url)
>
> Jakie s� wady/zalety mojej zmiany? S� �adniejsze rozwi�zania? Ch�tnie
> wys�ucha�bym bardziej obitych w projektach i moli ksi��kowych nt.
> projektowania.
>
> Jacek
>
> * Czy URL to twoja klasa, czy biblioteczna?
Niech będzie java.net.URL, ale skoro padło pytanie, ciekawym
rozwiązania, gdyby tak nie było.
> * Czy w ifach chodzi o to, że item jest url'em w postaci obiektu URL albo w
> postaci Stringa?
Dokładnie tak.
> * Jakiej klasy/interfejsu jest item?
Założmy, że na wejściu dostajemy Object, ale chętnie wysłuchałbym, co
by było, gdyby realizował pewien interfejs, np. IUrl.
Jacek
--
Jacek Laskowski
Java EE, functional languages and IBM WebSphere - http://blog.japila.pl
Warszawa JUG conference = Confitura (formerly Javarsovia) :: http://confitura.pl
Czyli masz klasę ItemHandler, która ma abstrakcyjną metodę
"handleItem(Object item)" i dziedziczące po niej URLItemHandler,
StringItemHandler, itp. Oraz kolekcję z obiektami tych klas, po której
iterujesz do czasu aż któryś z handlerów nie obsłuży item'a (załóżmy,
że metoda zwraca true, jeśli obsłużenie powiodło się).
> --
> Otrzymujesz tę wiadomość, ponieważ subskrybujesz grupę dyskusyjną Google o nazwie "Warszawa Java User Group (Warszawa JUG)".
>
> Aby zamieszczać posty w tej grupie, wyślij e-mail na adres warsza...@googlegroups.com.
> Aby anulować subskrypcję tej grupy, wyślij e-mail na adres warszawa-jug...@googlegroups.com.
> Aby uzyskać więcej informacji, odwiedź tę grupę pod adresem http://groups.google.com/group/warszawa-jug?hl=pl.
>
>
if (item instanceof URL) {
...
} else if (item instanceof String) {
...
} else...
W takim przypadku proponujďż˝
1. Nazwaďż˝ to, co robi kod w ifach - np. 'przekieruj do tego adresu'
2. W IUrl wprowadziďż˝ metodďż˝ redirect()
3. Kod z if�w przenie�� do implementacji metody redirect() w
poszczeg�lnych implementacjach IUrl
Wtedy zamiast if�w + instanceof mamy: item.redirect()
pozdr,
mb
W dniu 2011-07-06 22:09, Jacek Laskowski pisze:
> 2011/7/6 Michaďż˝ Bartyzel<mbartyz...@gmail.com>:
>
>> * Czy URL to twoja klasa, czy biblioteczna?
>
> Niech b�dzie java.net.URL, ale skoro pad�o pytanie, ciekawym
> rozwi�zania, gdyby tak nie by�o.
>
>> * Czy w ifach chodzi o to, �e item jest url'em w postaci obiektu URL albo w
>> postaci Stringa?
>
> Dok�adnie tak.
>
>> * Jakiej klasy/interfejsu jest item?
>
> Za�o�my, �e na wej�ciu dostajemy Object, ale ch�tnie wys�ucha�bym, co
> by by�o, gdyby realizowa� pewien interfejs, np. IUrl.
>
> Jacek
>
Właśnie trafiłem na poniższy kawałek kodu i przykuł moją uwagę, bo w
zasadzie "zmusił" mnie, aby go zamienić na rozwiązanie z metodami
przeciążonymi.
Ten kawałek kodu:
if (item instanceof URL) {
...
} else if (item instanceof String) {
...
} else...
zamieniłbym na:
void doSth(URL url)
void doSth(String url)
Jakie są wady/zalety mojej zmiany? Są ładniejsze rozwiązania? Chętnie
wysłuchałbym bardziej obitych w projektach i moli książkowych nt.
projektowania.
Utworzyć sobie klasę, która udostępnia metodę redirect(Object), a w
środku ma różne prywatne odmiany dla różnych typów.
Swoją drogą można to machnąć jako scalowy object i nie ma później
problemu z tworzeniem obiektów. Jak musisz robić w pure javie to
wewnętrzna klasa prywatna.
Pozdrawiam
Bartek "Koziołek" Kuczyński
http://koziolekweb.pl
Lepiej pomyśleć dwa razy i zacząć programować
niż dwa razy programować i potem zacząć myśleć
\ /
~00~
\_/
|||
W dniu 6 lipca 2011 22:21 użytkownik Michał Bartyzel
<mbartyz...@gmail.com> napisał:
> Jeśli zakładamy, że jest IUrl, którego implementacje
> opakowują URL oraz String, to kod z poszczególnych ifów
> ma ze sobą coś wspólnego.
>
>
> if (item instanceof URL) {
> ...
> } else if (item instanceof String) {
> ...
> } else...
>
>
> W takim przypadku proponuję
> 1. Nazwać to, co robi kod w ifach - np. 'przekieruj do tego adresu'
> 2. W IUrl wprowadzić metodę redirect()
> 3. Kod z ifów przenieść do implementacji metody redirect() w poszczególnych
> implementacjach IUrl
>
> Wtedy zamiast ifów + instanceof mamy: item.redirect()
>
>
>
> pozdr,
> mb
>
> W dniu 2011-07-06 22:09, Jacek Laskowski pisze:
>>
>> 2011/7/6 Michał Bartyzel<mbartyz...@gmail.com>:
>>
>>> * Czy URL to twoja klasa, czy biblioteczna?
>>
>> Niech będzie java.net.URL, ale skoro padło pytanie, ciekawym
>> rozwiązania, gdyby tak nie było.
>>
>>> * Czy w ifach chodzi o to, że item jest url'em w postaci obiektu URL albo
>>> w
>>> postaci Stringa?
>>
>> Dokładnie tak.
>>
>>> * Jakiej klasy/interfejsu jest item?
>>
>> Założmy, że na wejściu dostajemy Object, ale chętnie wysłuchałbym, co
>> by było, gdyby realizował pewien interfejs, np. IUrl.
>>
>> Jacek
>>
>
Jeśli jednak z jakiegoś powodu potrzebna ta wersja ze Stringiem
zrobiłbym tak:
void doSth(String url) { doSth(new URL(url)) }
Jeśli te metody robią jednak coś zupełnie innego, to chyba lepiej dać im
różne nazwy dla jasności:
void zróbcoś(URL url)
void zróbcośInnego(String url)
A te wspomniane przez was rozwiązania z if(url instanceof ...) czy z
IUrl zostawiłbym dla bardziej skomplikowanych sytuacji, a ta tutaj chyba
taka nie jest. :-)
> Czyli masz klasę ItemHandler, która ma abstrakcyjną metodę
> "handleItem(Object item)" i dziedziczące po niej URLItemHandler,
> StringItemHandler, itp. Oraz kolekcję z obiektami tych klas, po której
> iterujesz do czasu aż któryś z handlerów nie obsłuży item'a (załóżmy,
> że metoda zwraca true, jeśli obsłużenie powiodło się).
Dla niewielkiego zestawu możliwych przypadków, powiedzmy 2-4, mam
wrażenie, że to przerost formy nad treścią. Zupełnie nie pasuje mi to
podejście. W zasadzie, my oprogramowujemy coś (decyzja, czy możemy coś
wykonać), co zrobi za nas doskonale kompilator i JVM.
To wybrnąłeś sprytnie. A co w sytuacji, kiedy nie są? To uważam za tą
trudniejszą sytuację, bo wspólny interfejs, to prościzna i nie trzeba
wielkiej wiedzy projektowej :) Oczekuję więcej od praktyków :P
> Utworzyć sobie klasę, która udostępnia metodę redirect(Object), a w
> środku ma różne prywatne odmiany dla różnych typów.
Czy nie prościej/ładniej wystawić redirect(IUrl), jeśli to ma
odpowiadać propozycji Michała?!
> Prawdoposobnie tutaj obie metody robią to samo, tylko jedna przyjmuje URL-a
> jako URL, a druga jako String?
> Wtedy ja by m po prostu dał jedną metodę:
> void doSth(URL url)
> Jak ktoś bardzo chce bawić się stringami to niech woła: doSth(new
> URL(urlJakoString)). Ma to taką zaletę, że jak masz dziesięć takich metod
> doSth(URL url), to nie musisz dla każdej z nich pisać dwóch przeciążonych
> wersji i paskudzić sobie API ("It seems that perfection is attained not when
> there is nothing more to add, but when there is nothing more to remove").
To wciąż nie rozwiązuje głównego problemu, gdzie muszę sprawdzić typ
parametru, przez instanceof przykładowo, i wywołać odpowiednią metodę,
nieprawdaż? :) Wolałbym wycisnąć jak najwięcej z jvm (i wykorzystać
czas na inne dywagacje, które znowu zaoszczędzą mi trochę czasu, który
znowu poświęcę na dywagacje, itp. - innymi słowy - nigdy i tak nie
będę miał więcej wolnego czasu :))
2011/7/7 Irek Matysiewicz <iir...@gmail.com>:
To wciąż nie rozwiązuje głównego problemu, gdzie muszę sprawdzić typ
> Prawdoposobnie tutaj obie metody robią to samo, tylko jedna przyjmuje URL-a
> jako URL, a druga jako String?
> Wtedy ja by m po prostu dał jedną metodę:
> void doSth(URL url)
> Jak ktoś bardzo chce bawić się stringami to niech woła: doSth(new
> URL(urlJakoString)). Ma to taką zaletę, że jak masz dziesięć takich metod
> doSth(URL url), to nie musisz dla każdej z nich pisać dwóch przeciążonych
> wersji i paskudzić sobie API ("It seems that perfection is attained not when
> there is nothing more to add, but when there is nothing more to remove").
parametru, przez instanceof przykładowo, i wywołać odpowiednią metodę,
nieprawdaż? :) Wolałbym wycisnąć jak najwięcej z jvm (i wykorzystać
czas na inne dywagacje, które znowu zaoszczędzą mi trochę czasu, który
znowu poświęcę na dywagacje, itp. - innymi słowy - nigdy i tak nie
będę miał więcej wolnego czasu :))
Pozdrawiam
Bartek "Koziołek" Kuczyński
http://koziolekweb.pl
Lepiej pomyśleć dwa razy i zacząć programować
niż dwa razy programować i potem zacząć myśleć
\ /
~00~
\_/
|||
2011/7/7 Irek Matysiewicz <iir...@gmail.com>:
To wciąż nie rozwiązuje głównego problemu, gdzie muszę sprawdzić typ
> Prawdoposobnie tutaj obie metody robią to samo, tylko jedna przyjmuje URL-a
> jako URL, a druga jako String?
> Wtedy ja by m po prostu dał jedną metodę:
> void doSth(URL url)
> Jak ktoś bardzo chce bawić się stringami to niech woła: doSth(new
> URL(urlJakoString)). Ma to taką zaletę, że jak masz dziesięć takich metod
> doSth(URL url), to nie musisz dla każdej z nich pisać dwóch przeciążonych
> wersji i paskudzić sobie API ("It seems that perfection is attained not when
> there is nothing more to add, but when there is nothing more to remove").
parametru, przez instanceof przykładowo, i wywołać odpowiednią metodę,
nieprawdaż? :) Wolałbym wycisnąć jak najwięcej z jvm (i wykorzystać
czas na inne dywagacje, które znowu zaoszczędzą mi trochę czasu, który
znowu poświęcę na dywagacje, itp. - innymi słowy - nigdy i tak nie
będę miał więcej wolnego czasu :))
--
A strategie, dodatkowe interfejsy i co tam jeszcze wydają mi się 'lekkim' nadinżynierowaniem (skoro jest to dyskusja Jacka to nie wypada używać słów angielskich :P)
Jeśli to ma być potem jeszcze używane przez ludzi i czytelne i odporne na błędy itd to strategia zdaje się najlepsza w tym przypadku, choć myślę, że przekombinowana.
jeśli będzue uzywane przez ludzi i czytelne??
szczerze mówiac to moim zdaniemif (COŚTAM)return X;elsereturn Y;jest DUŻO czytelniejsze niż strategia, która z natury jest porozwalana po kilku klasach. IMHO strategia jest dobrym wyborem, jeśli lista IFów jest bardzo długo, lub jeśli jesteśmy PEWNI, że w niedługim czasie będziemy musieli dołożyć kolejne warunki.
> zainteresuj się wzorcem "strategia", o którym wspomniał Piotr.
>
> Prosty przykład:
> Map handlers = new HashMap().add(String.class, new
> StringHandler()).add(URL.class, new UrlHandler())
Ja widzę to jak rozwiązanie z przeciążonymi metodami tyle tylko, że w
moim rozwiązaniu rolę wyznaczania obsługi danego typu zrzucam na barki
jvm. W Twoim rozwiązaniu zakładasz, że typ jest kluczem, a tak działa
właśnie Java z przeciążonymi czy przesłoniętymi metodami.
Uzupełniam moją wcześniejszą wypowiedź: "Od praktyków wymagam więcej"
myślenia niż gadania :)
If (...) {
//...
} else
if (...) {
//...
} else
...
Co zasugerowało mi (ten wielokropek na końcu), że ifów będzie dużo.
Dlatego zaproponowałem strategię. Natomiast jeśli ma być ich 2-4 (jak
później sprecyzował), to rzeczywiście zależy od konkretnego przypadku.
Co do przykładów, gdzie zalecacie tworzenie URL'a na podstawie
String'a, to pamiętajcie, że konstruktor klasy URL rzuca wyjątkiem, a
my za bardzo nie wiemy, jak go obsłużyć. Zatem lepszym rozwiązaniem
byłoby już wymuszenie na użytkowniku przekazywania Stringa.
Kolejnym rozwiązaniem, które *być może* dałoby się zaadaptować jest
opakowanie tych Stringów i URLi i czego tam jeszcze w jedną klasę
(właną) i stworzenie jej różnych konstruktorów (z parametrem String,
URL, itp.) a następnie przekazywanie obiektu tej klasy jako argumentu
dla metody doSth(). Ale to da się zastosować tylko dla konkretnych
przypadków - wciąż nie wiemy, co ma robić metoda doSth() i czemu ważne
było rozróżnienie typów.
Kolejnym rozwiązaniem (przy użyciu Grooviego) byłoby dołożenie
metod(y) do klasy Object i przeciążenie ich w String, URL (i innych
wymaganych), które wykonywałyby to, co chcemy osiągnąć lub pozwalały
np. konwertować wszystko na jeden spójny format. Następnie obiekt w
takim formacie dałoby radę przekazać do metody doSth(). Chodzi mi o
coś takiego:
Object o = ... // to co przekazał user
FajnaKlasaWspolna tempArg = o.convertToFajnyFormat();
doSth(tempArg);
Ale to rozwiązanie jest moim zdaniem brzydkie i brudzące w kodzie. Ale
zawsze jakieś ;D hehe ;)
Pzdr.
W dniu 7 lipca 2011 11:37 użytkownik Michal Margiel
<michal....@gmail.com> napisał:
Od praktyk�w oczekujesz pewnie rozwi�zania problemu. Postawi�e� problem,
otrzyma�e� klika rozwi�za�. Ka�y, kto opodwiedzia� poda� za�o�enia, przy
kt�rych jego rozwi�zanie ma sens. Je�li nie jeste� zadowolny, to pewnie
nie szuka�e� rozwi�znia problemu, tylko ciekawej dyskusji :) Albo nie
do�� szczeg�owo opisa�e� problem, jego kontekst i jakiego konkretnie
efektu siďż˝ spodziewasz.
pozdr,
mb
> Od praktyków oczekujesz pewnie rozwiązania problemu. Postawiłeś problem,
> otrzymałeś klika rozwiązań. Każy, kto opodwiedział podał założenia, przy
> których jego rozwiązanie ma sens. Jeśli nie jesteś zadowolny, to pewnie nie
> szukałeś rozwiąznia problemu, tylko ciekawej dyskusji :) Albo nie dość
> szczegółowo opisałeś problem, jego kontekst i jakiego konkretnie efektu się
> spodziewasz.
Większość z propozycji była w moim odczuciu odejściem od głównego
problemu, jakby jego zaowalowaniem. Mam kilka ifów i chciałbym
zniwelować je rozwiązaniami już dostępnymi w jvm, w języku, a nie
oprogramowywać je. Kiedykolwiek kontrowałem propozycję, podawałem
powody, dla których to robię. Ja znalazłem rozwiązanie i nie
zauważyłem, aby ktokolwiek je wyciął jako nieodpowiednie, więc
mniemam, że mam rozwiązanie, ale bez wiary w swoje umiejętności
programistyczne, a na pewno projektowe, prosiłem o kontrpropozycje. Te
kilka propozycji, które padły, faktycznie nie były w pelni dla mnie
zadowalające, ale mam już świadomość, że może nie ma rozwiązania
lepszego? Czuję się zaszczycony moim wnioskiem :)
> Mysle, ze ocena dowolnego rozwiazania tez powinna brac pod uwage w jakim
> kierunku spodziewamy sie przyrost funkcjonalnosci/kodu wokol tych if-ow.
Właśnie tu mam pewien problem, bo po tej dyskusji skłaniam się ku
podejściu, aby w ogóle zaniechać ifów. Chyba mnie pokręciło :)
CzescMysle, ze ocena dowolnego rozwiazania tez powinna brac pod uwage w jakim kierunku spodziewamy sie przyrost funkcjonalnosci/kodu wokol tych if-ow.
Na pewno ktos inny bedzie dodawal przypadki, jak bedzie mu wygodnie dodac to zrobi i pojdzie dalej bez patrzenia. Wazne tez, zeby trudno bylo zrobic blad przy modyfikacji.
ale jak będziemy za głęboko w to wchodzić taka dyskusja staje się czysto akademicka nie wnosząca nic nowego, bo niemal każdy problem można dobrze rozwiązać na wiele sposobów.
> Ale tego często nie wiesz, czy będą wymagane zmiany.
...
> weźmy pod uwage to, że inni w naszym zespole też sa dobrymi programistami (a jeśli nie to
> zrobimy ich takimi siedząc z nimi w parze ;))
Gdybym nie przeczytał kto to napisał, nigdy, ale to nigdy nie
powiedziałbym, że to nasz MM :)
> Pytanie jest czy ponizszy kod jest czytelny i pokusilibyscie sie o
> refaktoring tego kodu - metody rank(szczegolnie ify), aby zrobic ten kod
> "bardziej czytelny"?
Dla mnie jest wystarczająco czytelny i nic bym nie zmienił, poza
wprowadzeniem stałej dla -1, która niewprawne oka (moje wliczając)
przykuwa swoją tajemniczością i lekko irytuje :)
2011/7/8 Michal Margiel <michal....@gmail.com>:
...
> Ale tego często nie wiesz, czy będą wymagane zmiany.
> weźmy pod uwage to, że inni w naszym zespole też sa dobrymi programistami (a jeśli nie toGdybym nie przeczytał kto to napisał, nigdy, ale to nigdy nie
> zrobimy ich takimi siedząc z nimi w parze ;))
powiedziałbym, że to nasz MM :)
2011/7/8 Adam Lider <adam....@googlemail.com>:
Dla mnie jest wystarczająco czytelny i nic bym nie zmienił, poza
> Pytanie jest czy ponizszy kod jest czytelny i pokusilibyscie sie o
> refaktoring tego kodu - metody rank(szczegolnie ify), aby zrobic ten kod
> "bardziej czytelny"?
wprowadzeniem stałej dla -1, która niewprawne oka (moje wliczając)
przykuwa swoją tajemniczością i lekko irytuje :)
Warszawa JUG conference = Confitura (formerly Javarsovia) :: http://confitura.pl
A wracając jeszcze do ifów, to jest jedna sprawa, w której się można
"rąbnąć" - mówię o przypadku z pierwszego postu. Otóż jeżeli mamy tam
instanceof-y, to pamiętajmy, że instanceof zwraca true także dla klas
pochodnych (nie tylko wymienionej), zatem istnieje ryzyko, że
świadomie albo nieświadomie umieścimy if-y w złej kolejności i będzie
trudny do wykrycia błąd.
O ile pamiętam, to w Javie 7 ma być dostępny switch po Stringach,
wtedy lepszym rozwiązaniem byłoby "switchowanie" po nazwie klasy
(obj.getClass().getCanonicalName() lub coś takiego...) - jest to
rozwiązanie "przyszłościowe", natomiast wykorzystujące JVM i
mechanizmy języka ;p ;)
Pzdr.
W dniu 8 lipca 2011 12:45 użytkownik mproch Gazeta.pl
<mpr...@gazeta.pl> napisał:
> A wracając jeszcze do ifów, to jest jedna sprawa, w której się można
> "rąbnąć" - mówię o przypadku z pierwszego postu. Otóż jeżeli mamy tam
> instanceof-y, to pamiętajmy, że instanceof zwraca true także dla klas
> pochodnych (nie tylko wymienionej), zatem istnieje ryzyko, że
> świadomie albo nieświadomie umieścimy if-y w złej kolejności i będzie
> trudny do wykrycia błąd.
Bardzo dobra uwaga. Faktycznie o tym w ogóle nie myślałem, a może
przysporzyć problemów.
> O ile pamiętam, to w Javie 7 ma być dostępny switch po Stringach,
> wtedy lepszym rozwiązaniem byłoby "switchowanie" po nazwie klasy
> (obj.getClass().getCanonicalName() lub coś takiego...) - jest to
> rozwiązanie "przyszłościowe", natomiast wykorzystujące JVM i
> mechanizmy języka ;p ;)
Ta nowość, to porównywanie po String.equals() (było wczoraj podczas
testu na spotkaniu powitalnym j7) i w zasadzie nie widzę dla tego
zastosowania (poza upiększeniem wyglądu kodu, ale niekoniecznie jego
kształtu).
Wciąż uważam, że jeśli cokolwiek miałbym zmienić w pierwotnym kodzie,
to byłoby to właśnie przeciążanie (i tak zrobię w poprawce). Dzięki za
sugestie.
> Ta nowość, to porównywanie po String.equals() (było wczoraj podczas
> testu na spotkaniu powitalnym j7) i w zasadzie nie widzę dla tego
> zastosowania (poza upiększeniem wyglądu kodu, ale niekoniecznie jego
> kształtu).
Ok, co kto woli :) Ja bym wolał mieć to w postaci switcha po stringach
a można mieć też drabinkę if-ów ze String.equals().
--
Otrzymujesz tę wiadomość, ponieważ subskrybujesz grupę dyskusyjną Google o nazwie "Warszawa Java User Group (Warszawa JUG)".
Aby zamieszczać posty w tej grupie, wyślij e-mail na adres warsza...@googlegroups.com.
Aby anulować subskrypcję tej grupy, wyślij e-mail na adres warszawa-jug...@googlegroups.com.
Aby uzyskać więcej informacji, odwiedź tę grupę pod adresem http://groups.google.com/group/warszawa-jug?hl=pl.
W Javie double dispatch (albo ogólniej: multiple dispatch) można
'emulować' za pomocą wielu technik (na przykładzie Jacka z jego metodą
doSth):
- if-ów: void doSth(Klasa obj) { if(obj instanceof Podklasa1) { ... }
else if(obj instanceof Podklasa2) { ... } }
- switchów: void doSth(Klasa obj) { switch(obj.getTyp()) { case
PODKLASA1: ...; case PODKLASA2: ...} }, dodatkowo Groovy i języki
funkcyjne mają superwypasione wersje switchów
- wzorca Visitor: void doSth(Klasa obj) { obj.accept(new KlasaVisitor()
{ void podklasa1() {...} void podklasa2() { ... } }) }
- fabryczek + wzorca Strategia: void doSth(Klasa obj) {
fabryka.dajMiDoSth(obj.getClass()).wykonaj() }
- modyfikowalnych fabryczek (np. hashmapy, whiteboard pattern, rejestr
Windows): fabryczka[Podklasa1.class] = { kod1 };
fabryczka[Podklasa2.class] = { kod2 }; void doSth(Klasa obj) {
fabryka.dajMiDoSth(obj.getClass()).wykonaj() }
- i właśnie przeciążanie metod: void doSth(Podklasa1 obj) { ... } void
doSth(Podklasa2 obj) { ... }. Akurat w Javie wybór przeciążonej metody
następuje w czasie kompilacji, ale można to przenieść do runtime'u
dodając trzecią metodę: void doSth(Klasa obj) {
getClass().getMethod("doSth", obj.getClass()).invoke(this, obj) }.
- invokedynamic z Javy 7 - jeszcze nie próbowałem, ale to się chyba da
zrobić:
http://download.java.net/jdk7/docs/technotes/guides/vm/multiple-language-support.html
+
http://weblogs.java.net/blog/forax/archive/2011/01/07/calling-invokedynamic-java
To jest tylko wybór narzędzia. Wszystkie robią z grubsza to samo, i
wybór to chyba tylko kwestia czy (i jak) ten kod będzie ewoluował w
przyszłości, wydajności, albo po prostu gustu, i stąd na pytanie Jacka
pojawiło się tyle rozwiązań, ale skoro nie znamy szerszego kontekstu, to
w myśl KISS czy YAGNI stosujemy najprostsze rozwiązanie, a nim jest
właśnie przeciążanie metod, albo if-else. :-)
To po co String.valueOf(...) w tylu wydaniach, odpowiednio dla każdego typu?!
http://download.oracle.com/javase/6/docs/api/java/lang/String.html
> uważam jednak, że należałby się koniecznie przyjrzeć dlaczego item może mieć
> kilka postaci, bo być może smrodek dochodzi z innego miejsca, a wtedy klasę
> z tą nieszczęsną metodą być możne da się przekształcić w:
Co Wy z tym smrodkiem?! Zaczynam czuć się jak klient, który mówi, że
chce gofra i w zależności od zaawansowania budki słyszy w odpowiedzi
"Proszę", albo "A z jakimi dodatkami, kształtem, smakiem, kolorem,
itp." :)
Różne miejsca powstawania item, to np. pochodzi z warstwy webowej z
żądania (jako String) lub przez zdalne wywołanie RMI (jako Object).
> class URLHandler {
> void soSth(URL u){...};
> }
> class StringHandler extends URLHandler{
> void soSth(String s){
> super.doSth(new URL(s));
> };
> }
> i wtedy od stworzenia item'a towarzyszy mu odpowiedni handler.
Ale wtedy sprowadza się to efektywnie do instanceof, którą musi
obsłużyć programista. Ja tego nie chcę, bo wiem, że JVM z
przeciążonymi metodami zrobi to za mnie. Moje pierwotne pytanie
zmierzało do znalezienia bardziej zaawansowanego rozwiązania (jeśli
takowe w ogóle istnieje i bez określania, czym "bardziej zaawansowane"
jest).
Podejrzewam, �e String.valueOf() istnieje z powod�w wydajno�ciowych.
Normalnie wo�asz: obiekt.toString(), ale na typach prymitywnych (int,
long, ...) trzeba coďż˝ w stylu Integer.toString(...). valueOf tak jakby
ukrywa te r�nice: valueOf(cokolwiek) zawsze przerobi to na stringa.
Gdyby nie chodzi�o o wydajno��, to po prostu wystarczy�aby valueOf(Object).
Gdyby to ode mnie zale�a�o, by�oby w Javie tak jak jest w Scali czy w
C#: cokolwiek to jest, zawsze mo�esz wywo�a� obiekt.toString(), a
sprytny kompilator i tak to sam zoptymalizuje - kto� mocno nie pomy�la�
przy tworzeniu pierwszej wersji Javy. Podobnie gdyby nie chodzi�o o
powody wydajno�ciowe, zamiast poprzeci��anych metod, w Math.max()
powinno byďż˝ tam po prostu <T extends Comparable<T>> Math.max(T x, T y).
W valueOf dla czegokolwiek co przeka�esz zachowanie by�o okre�lone
(ka�dy obiekt mo�na przerobi� na stringa), dla wszystkiego co jest
Comparable mo�esz zdefiniowa� zachowanie max. Tw�j przypadek by� nieco
inny: doSth(Object obj) { if(obj instanceof String) { zr�b to } else if
(obj instanceof URL) { zr�b tamto } else { throw new
IllegalArgumentException() } } - nie dla wszystkich dopuszczonych
obiekt�w mamy zdefiniowane zachowanie.
Jest to mniej odporne na b��dy i mniej czytelne dla programisty ni� dwie
przeci��one metody: doSth(String), doSth(URL) - wystarczy wcisn��
ctrl+spacja i wida� o co chodzi, przy doSth(Object) by�oby to mniej
jasne. Cho� wszystkie sposoby robi� to samo, r�ni� si� troch�
(wydajno��, sprawdzenia kompilatora, mo�liwo�� rozbudowy, prostota). Na
czym ci najbardziej zale�y, tak� technik� wybierasz, nie mo�na mie�
wszystkiego na raz.
2011/7/9 Sławek Sobótka<sso...@gmail.com>:
Zacznę od tego, że przeciążanie metod nie jest żądną techniką
projektową w Javie ponieważ nie rozwiązuje żadnego problemu. Wciąż
musisz wybrać w czasie kompilacji wywoływaną metodę.
To po co String.valueOf(...) w tylu wydaniach, odpowiednio dla każdego typu?!
http://download.oracle.com/javase/6/docs/api/java/lang/String.html
W String.valueOf() w Math.max() to prawdopodobnie nie wybór tylko
optymalizacja polimorfizmu jak pisałem wcześniej:
String.valueOf(Object) działa zarówno na typach prymitywnych jak i
referencyjnych, ale w przypadku typów prymitywnych wymaga autoboxingu
(np. int -> Integer), a boxing wymaga alokacji obiektu, a alokacja
obiektu choć w Javie jest bardzo szybka, i tak jest duuużo wolniejsza od
wywołania metody, a zbędnego boxingu optymalizować nie potrafi ani javac
ani HotSpot JVM (tak przynajmniej było z pół roku temu), i m.in. z tego
powodu metody te są dodatkowo poprzeciążane dla wszelakich typów
prymitywnych: valueOf(int), valueOf(long), itd. Jeśli typ znany jest w
czasie kompilacji zostanie użyta zoptymalizowana wersja przeciążona, a
jeśli nie, to trudno - następi boxing i unboxing.
Kompilator Scali potrafi dokonywać takich paskudnych optymalizacji
automatycznie: bierze zróbCoś(T) i potrafi automatycznie to
"wyspecjalizować" dla wszystkich typów prymitywnych (zróbCoś(int),
zróbCoś(long), ...).
Ja wiem że ty wiesz, ty wiesz że ja wiem, ale jest tu kilkaset osób i na
pewno nie wszyscy wiedzą. :-)
Co prawda Java nie wspiera double dispatch, ale z drugiej strony użycie
tego sposobu z refleksją do emulacji double dispatch nie jest takie
trudne, wobec tego przeciążanie metod w Javie nie jest takie złe. (co
innego np. w C++ - tam trik z refleksją nie zadziała bo standardowy C++
refleksji nie ma)
> (zawsze daję się Irkowi uwikłać w żeglugę na wodach bliskich
> kompilatora;)
Bo kompilatory i języki programowania, i ich jakość określają sposób w
jaki myślimy o kodzie i ogólnie wpływają na jakość naszej pracy.
Kompilator to najważniejsze narzędzie programisty: bez Eclipsa jakośtam
przeżyjesz, bez Bugzilli jakośtam przeżyjesz, bez SVN-a i Mavena
jakośtam przeżyjesz, bez JUnita jakośtam przeżyjesz, ale bez kompilatora
raczej niewiele zdziałasz.
Dla przykładu, zespół do którego teraz trafiłem w pracy nie używa ani
Bugzilli (czy czegokolwiek podobnego), ani Mavena (czy czegokolwiek
podobnego), ani JUnita (czy czegokolwiek podobnego), ani nawet SVN-a
(czy czegokolwiek podobnego - wymiana i integracja kodu odbywa się
mejlem), choć oczywiście o wiele, wiele lepiej by było gdyby te
narzędzia były też używane, ale dobry język programowania i kompilator
(czy interpreter) to absolutna podstawa, a im lepszy tym lepiej, dlatego
zawsze warto pogłębiać wiedzę z tego tematu.
--
Otrzymujesz tę wiadomość, ponieważ subskrybujesz grupę dyskusyjną Google o nazwie "Warszawa Java User Group (Warszawa JUG)".
Aby zamieszczać posty w tej grupie, wyślij e-mail na adres warsza...@googlegroups.com.
Aby anulować subskrypcję tej grupy, wyślij e-mail na adres warszawa-jug+unsubscribe@googlegroups.com.
Aby uzyskać więcej informacji, odwiedź tę grupę pod adresem http://groups.google.com/group/warszawa-jug?hl=pl.
W dniu 2011-07-06 21:59, Jacek Laskowski pisze:
> Cze��,
>
> W�a�nie trafi�em na poni�szy kawa�ek kodu i przyku� moj� uwag�, bo w
> zasadzie "zmusi�" mnie, aby go zamieni� na rozwi�zanie z metodami
> przeci��onymi.
>
> Ten kawa�ek kodu:
>
> if (item instanceof URL) {
> ...
> } else if (item instanceof String) {
> ...
> } else...
>
> zamieni�bym na:
>
> void doSth(URL url)
> void doSth(String url)
>
> Jakie s� wady/zalety mojej zmiany? S� �adniejsze rozwi�zania? Ch�tnie
> wys�ucha�bym bardziej obitych w projektach i moli ksi��kowych nt.
> projektowania.
>
> Jacek
>
Aż dziw bierze, że wciąż tak niewielu się dało ponieść fantazji
programistycznej i wziąć udział w dyskusji :)
Niektórzy w poniedziałek pracują :]
--
Jakub Nabrdalik
http://solidcraft.eu
> Niektórzy w poniedziałek pracują :]
Zakładam, że na tej grupie "niektórzy" to "wszyscy". To jest forum
WJUGa, a nie MiToLotto czy NieMamKredytuPracaToHobby :)
Jestem scrpting kid od PHP...
Pozdrawiam
Bartek "Koziołek" Kuczyński
http://koziolekweb.pl
Lepiej pomyśleć dwa razy i zacząć programować
niż dwa razy programować i potem zacząć myśleć
\ /
~00~
\_/
|||
> --
> Otrzymujesz tę wiadomość, ponieważ subskrybujesz grupę dyskusyjną Google o nazwie "Warszawa Java User Group (Warszawa JUG)".
>
> Aby zamieszczać posty w tej grupie, wyślij e-mail na adres warsza...@googlegroups.com.
> Aby anulować subskrypcję tej grupy, wyślij e-mail na adres warszawa-jug...@googlegroups.com.
Paweł
Ps. Hi parę razy, bo to optymalizacja.