-
Lilianne E. Blaze
>bartkiller napisał
>Jeśli już miałbym takie gówno napisać to szczerze
>mówiąc wolałbym nie odwalać za kompilator roboty. Po to
Z watku jasno wynika ze dla X osob scenariusz #1 jest niejasny, wiec moze warto dodac te 3-4 linie teraz zeby uniknac godzin watpliwosci i testow pozniej?
>jest przeciążanie metod, żeby takich rzeczy nie musieć
>pisać.
Trzy slowa. Jednolita obsluga bledow. Copy-paste programming.
Jak masz takich metod kilka-kilkanascie, to jak zamkniesz je w try-catch?
> Problem w tym, ze w tym przypadku obiekty Figura musza buc swiadome klasy Glowna, calej jej logiki i srodowiska.
Nie musza, wystarczy ze dostana w parametrach jakies Graphics, PaintContext czy whatever.
> Istnieje cos takiego co kompoilator i JVM uzywaja za nas - RTTI :), po to obiekty maja dodatkowy blok pamieci zeby mozna bylo zidentyfikowac ich prawdziwy typ - wlasnie ten blok jest uzywany przy operacji instanceof.
Szczerze watpie zeby byla jakas zauwazalna roznica wydajnosci miedzy przeciazaniem a instanceof, tym bardziej jesli mowimy o metodach z logika a nie getterach wywolywanych x razy na milli.
Przeciazenie jest najlepsze jesli robi sie cos tak samo na roznych parametrach. Np:
drawPoint(Point p) { drawPoint(p.x, p.y); }
drawPoint(int x, int y) { ... }
Albo symuluje parametry opcjonalne. -
boska renia
>Z watku jasno wynika ze dla X osob scenariusz #1 jest
>niejasny, wiec moze warto dodac te 3-4 linie teraz zeby
>uniknac godzin watpliwosci i testow pozniej?
Scenariusz 1 nie tyle jest niejasny, co po prostu błędny. -
Lilianne E. Blaze
>boska renia napisał
>>Z watku jasno wynika ze dla X osob scenariusz #1 jest
>>niejasny, wiec moze warto dodac te 3-4 linie teraz zeby
>>uniknac godzin watpliwosci i testow pozniej?
>
>Scenariusz 1 nie tyle jest niejasny, co po prostu błędny.
Moze: bledny i niejasny?; / -
boska renia
Uprzedzając, oto prosty dowód błędności i niejasności scenariusza 1:
Scenariusz 1:
Glowna{
void rysuj(Kolo kolo) { ... }
void rysuj(Figura figura} { throw new RuntimeException("WTF?"); }
void rysuj(Kwadrat kwadrat) { }
}
SypiacaKlasa{
void pokazStos(Glowna glowna, Figura figura){
glowna.rysuj(figura);
}
}
Efekt wywołania metody pokazStos() będzie zgodny z jej nazwą - zostanie rzucony okazały RuntimeException. Natomiast implementacja zgodnie ze scenariuszem 2 zadziała poprawnie (wywołując właściwą implementację metody rysuj) - niezależnie od typu obiektu. -
-
boska renia
> - niezależnie od typu obiektu.
poprawka: zgodnie z faktycznym typem obiektu Figura. -
bartkiller
>Lilianne E. Blaze napisała:
>Trzy slowa. Jednolita obsluga bledow. Copy-paste
>programming.
>
>Jak masz takich metod kilka-kilkanascie, to jak zamkniesz je
>w try-catch?
Zwróć uwagę na tryb przypuszczający w mojej wypowiedzi. Ja tak "nie miewam". Pomysł z gruntu jest zły, więc nie widzę sensu brnąć w niego dalej i się zastanawiać co jakby było kilkanaście - bo nie byłoby :) -
Lilianne E. Blaze
>bartkiller napisał
>Zwróć uwagę na tryb przypuszczający w mojej wypowiedzi.
>Ja tak "nie miewam". Pomysł z gruntu jest zły, więc nie
>widzę sensu brnąć w niego dalej i się zastanawiać co
>jakby było kilkanaście - bo nie byłoby :)
Ok, czyli jednak _mniej wiecej_ sie zgadzamy.
Osobiscie uwazam ze _czasami_ (praktycznie tylko wtedy kiedy chodzi o wspolprace z 3rd party libs) taka konstrukcja (jak #3 ) jest potrzebna lub po prostu wygodna, ale najczesciej da sie to zrobic inaczej. Nie przychodzi mi na mysl zaden scenariusz kiedy mialoby to sens w kodzie pisanym od zera. -
bartkiller
-
boska renia
>> Problem w tym, ze w tym przypadku obiekty Figura musza buc
>swiadome klasy Glowna, calej jej logiki i srodowiska.
>
>Nie musza, wystarczy ze dostana w parametrach jakies
>Graphics, PaintContext czy whatever.
>
W rzeczy samej, stan obiektu można zdefiniować w niezależnym obiekcie. Dokładnie w ten sposób zrealizowane jest obsługa dostępu do stanu w Java EE (czyli w terminologii JEE -- kontekstu).
Java EE API definiuje interfejsy, określające "publiczny" stan - takie jak np. EJBContext, SessionContext, EntityContext, itp. Jeśli zachodzi konieczność dostania się do "prywatnego" stanu kontenera EJB (w ramach konkretnej implementacji serwera Java EE) wystarczy rzucić obiekt kontekstu (opisany poprzez interfejs) na implementację (czyli klasę).
Przykładowo, dla kontekstu wywołania EJB (interfejs EJBContext) w GF będzie to com.sun.ejb.containers.EJBCont exImpl, w której to klasie znajdziemy dodatkowe parametry stanu wywołania ("prywatnego kontekstu"), niedostępne z poziomu Java EE API. -
george
>boska renia napisał
>Uprzedzając, oto prosty dowód błędności i niejasności
>scenariusza 1:
>
>Scenariusz 1:
>Glowna{
>void rysuj(Kolo kolo) { ... }
>void rysuj(Figura figura} { throw new
>RuntimeException("WTF?"); }
>void rysuj(Kwadrat kwadrat) { }
>}
>
Blednosci i neijasnosci?
Niejasna jest logika: jesli kolo to ta metoda, jesli kdwadrat to ta, jesli pozostale to inna?
Co jest niejasnego w tym scenariuszu?
np
Serializator{
zapisz(Warzywo )
zapisz(Jablko)
zapisz(Sliwa)
zapisz(Owoc)
}
wydaje mi sie calkiem prosty, jesli warzywo to zrob cos, jesli sliwka to zrob to dwa razy, jesli jablko tylko pol, jesli owoc to zrob cos zupelnie innego. Mozna sie tutaj wyzlaszczac nad powodem czemu kazda klasa nie wie jak sie zapisac, powod jest, super swietny i nie to jest przedmiotem rozmowy, tylko to dlaczego takie cos nie dziala.
>SypiacaKlasa{
> void pokazStos(Glowna glowna, Figura figura){
> glowna.rysuj(figura);
> }
>}
>
>Efekt wywołania metody pokazStos() będzie zgodny z jej
>nazwą - zostanie rzucony okazały RuntimeException.
>Natomiast implementacja zgodnie ze scenariuszem 2 zadziała
>poprawnie (wywołując właściwą implementację metody
>rysuj) - niezależnie od typu obiektu.
-
boska renia
Widać nie jest jeszcze dosyć jasno i wyraźnie naświetlone dlaczego ten scenariusz jest błędny;/ (w stosunku do pozostałych dwóch)
Scenariusz 1 jest błędny, ponieważ przekazując metodzie pokazStos() jakąkolwiek figurę (koło, kwadrat) zawsze zostanie odpalone rysuj(Figura) -- czyli zostanie rzucony RuntimeException. Wybranie metody w tym scenariuszu zachodzi w momencie kompilacji, a nie wywołania.
W scenariuszu 2 i 3 (oraz 4) zostanie natomiast wywołana metoda właściwa dla faktycznego typu figury; a to dlatego, że właściwa metoda jest wybierana dynamicznie, przez JVM. -
george
Hehe, no to sie nie zrozumeilismy. Wiem ze tak sie stanie, przetestowalem, poczytalem, zapamietalem. Wiem ze metoda "jest linkowana" w momencie kompilacji. Tylko czemu tak jest, skoro JVM ma mozliwosc sparawdzenia wszsytkiego? Czemu wykorzystuje ja tylko w przpadku nadpisywania metod? (albo ogolnie dziedziczenia - np genericsy)
Ale patrzac z perspektywy uzytecznosci mozna zaostasowac dwa podejscia:
1. Albo obiekty wiedza wszystko i metody sa implementowane w nich, wtedy zaleznie od prawdziwego typu obiektu
2. mamy trzeci klase ktora cos robi.
Pomijajac fakt ktore z podejsc jest lepsze, wydawaloby sie ze przytoczony przezemnie przyklad powinine smigac, a nawet nie podryguje.
Nie wiem moze pominolem ten rozdzial jak sie uczylem ale bylem przeswiadczony ze taki kod powinien zadzialac, albo poprostu polimorfizm dal mi taka zludna nadzieje. -
boska renia
Szczerze mówiąc, nie bardzo rozumiem dwa podejścia, proszę trochę jaśniej;)
>Tylko czemu tak jest, skoro JVM ma mozliwosc sparawdzenia >wszsytkiego? Czemu wykorzystuje ja tylko w przpadku nadpisywania >metod?
Nasuwają mi się trzy argumentacje: 1) przeciążanie metod jest mechanizmem statycznym, wziętym jeszcze z języka C 2) wybieranie dynamiczne metod jest znacznie wolniejsze 3) byłoby źródłem problemów i "cudownych" zachowań (np. w przypadku wartości null która metoda byłaby wybierana? JVM rzucałby monetą??).
Trzeci punkt jest chyba najważniejszy. Java zrezygnowała z magii charakterystycznej dla C/C++ na rzecz konieczności ręcznego wstukiwania/wymuszania właściwych zachowań. Jest to na pewno zdrowsze dla jakości powstającego kodu, ułatwia ogarnięcie przez programistę, a szczególnie pracę grupową, kiedy nie wszyscy mają podobne zrozumienie tematu. Jak dla mnie to C/C++ w stosunku do Javy to jak język francuski (niemiecki) do angielskiego. Łatwiej na pewno rozmawia się w mniej złożonym języku;)
Jedyną więc możliwością jest wybieranie metody przeładowanej przez kompilator; w trakcie wywołania wybranie właściwej metody przeciążonej mogłoby być niedeterministyczne, a więc byłoby to niedopuszczalne.
Genericsy natomiast, również są mechanizmem statycznym, realizowanym w czasie kompilacji. -
boska renia
mamy dwie metody:
Serializator{
zapisz(Sliwka sliwka);
zapisz(Pomarancza pomarancza);
zapisz(Owoc owoc);
}
oraz zakładając, że metoda przeładowana jest w momencie wywołania (przez JVM, a nie kompilator), to powstaje pytanie: która metoda zostałaby wywołana w momencie przekazania wartości null do metody serializuj?
void serializuj(Owoc owoc){
serializator.zapisz(owoc);
} -
george
proste, pytanie z zakresu SJCP :) w przypadku wartosci null przewazajacym jest typ referencji. w przyapdku czystego nulla podanego "z palca" - compile error time.
Wolniejsze? Nie koniecznie. Roznica moze byc jedynie przy skomplikowanych drzewach dziedziczenia, lub gdy jestesmy pewni ze uzywamy tylko jakiejsc czesci calego drzewa - ale nie ma roznicy - przynajnmiej tak mi sie zdaje ze JVM wykorzystuje instanceof - zaglada do tej czesci obiektu ktora przechowuje informacje o jego prawdziwym typie itp. Czyli w przewazajacej czesci przypadkow nie byloby ubytku w szybkosci.
Podejscia == przytoczone scenariusze mniej wiecej. -
bartkiller
>boska renia napisał
>Java zrezygnowała z magii charakterystycznej dla C/C++ na rzecz >konieczności ręcznego wstukiwania/wymuszania właściwych zachowań
:O no akurat sposób wybierania wywoływanej metody jest taki sam -
boska renia
>proste, pytanie z zakresu SJCP :) w przypadku wartosci null
>przewazajacym jest typ referencji. w przyapdku czystego
Dodałem hipotetyczne założenie: wybieranie metody realizowane jest dynamicznie. Takie dynamiczne wybieranie kłóciłoby się też z polimorfizmem - programista nigdy nie byłby pewien która metoda przeciążona zostanie faktycznie wybrana, bowiem rozszerzając klasę o kolejną metodę przeciążoną można by zmienić sposób zachowania - a zmiana działania kodu nie wynikałaby z polimorfizmu. Byłoby to źródłem niedopuszczalnych błędów.
Argumentów można podawać jeszcze wiele, ale jest to bezcelowe, bo język taki jest, jaki jest i tego nie zmienimy. Dynamiczne wybieranie metody w Javie realizuje się za pomocą polimorfizmu, albo instanceof -- jest to wystarczające i zgodnie z założeniem języka - rozsądnie proste.
>boska renia napisał
>Java zrezygnowała z magii charakterystycznej dla C/C++ na rzecz >konieczności ręcznego wstukiwania/wymuszania właściwych zachowań
>:O no akurat sposób wybierania wywoływanej metody jest taki sam
Myślałem tu właśnie o różnych "cudach" z języków C/C++, które w Javie dzięki bogu w Javie nie znalazły.
A jeśli ktoś ma wątpliwości, która metoda przeciążona zostanie wywołana, to niech odpali Eclipse'a, lub inne IDE. Wystarczy odpalić Ctrl i klikniąć na metodę i już wiadomo, która metoda przeciążona zostanie faktycznie wykonana. Na etapie designu, a nie runtime'u. -
bartkiller
>boska renia napisał
>Myślałem tu właśnie o różnych "cudach" z języków
>C/C++, które w Javie dzięki bogu w Javie nie znalazły.
Może masz na myśli szablony ? :DDDDDDDDDDDddddd :P -
boska renia
mam na półce klasyczną książkę o C++ o objętości jakiś 800 stron. Autor twierdzi, że w tym języku można wyrazić wszystko. Nawet nie chce zaglądać, co z tego wszystkiego nie zostało przeniesione do Javy;] -
bartkiller
- Przeglądaj grona w kategorii Internet i Komputery
- Przeglądaj grona w okolicy Warszawa
- Załóż własne grono tematyczne
- Zostań moderatorem
Podobne Tematy
|
|
Wszystko co związane z programowaniem w Java (J2EE, JSP, JDBC, itd) test
Miejsca grona (1)
-
Kino Luna ul. Marszałkowska, Warszawa
www.kinoluna.pl kino.luna@maxfilm.com.pl 22 621 78 28
- Dodaj miejsce

