Problem klasa generyczna - hello world.
Seweryn =?ISO-8859-2?Q?Habdank=2DWojew=F3dzki?= - 04-04-2006 00:09
Problem klasa generyczna - hello world.
Witam
Mam taką klasę:
public class generic_test<T> {
public T elem;
public generic_test(T elem) { this.elem = elem; } }
Oraz
public class Main {
public Main() { }
public static void main(String[] args) { generic_test<Integer> elem1; generic_test<Double> elem2; // generic_test<int> elem0; // * } }
I mam pytania:
1. Dlaczego nie działa linijka oznaczona "// *", gdzie w specyfikacji jest to wytłumaczone, jasne jest dla mnie, że typ int nie daje referencji i to pewnie nie będzie działać dla żadnego POD'a. Ale gdzie to jest napisane w opisie języka, aby poczytać szerzej na ten temat. Czy można liczyć na jakieś "boxingi" jeżeli ktoś poda double zamiast Double w kontekście klas generycznych?
2. Jak zrobic specjalizację dla różnych typów. Chodzi mi o sytuację, że jeżeli mam typ T który jest czymś ala macierz to czasem doniego jest dostęp poprzez np. get(i,j), czasem inaczej a zatem chciałbym mieć generyczny wraper do pobierania elementów z np. macierzy. Co ogólnie jest ważne jeżeli kod dla poszczególnych typów jest inny.
Pozdrawiam.
--
|\/\/| Seweryn Habdank-Wojewódzki `\/\/
Grzegorz Głowaty - 04-04-2006 00:10
Użytkownik "Seweryn Habdank-Wojewódzki" <habdank@gmail.com> napisał w wiadomości news:e0r464$juq$1@tkdami.pl... > Witam > > Mam taką klasę: > > public class generic_test<T> { > > public T elem; > > public generic_test(T elem) { > this.elem = elem; > } > } > > Oraz > > public class Main { > > public Main() { > } > > public static void main(String[] args) { > generic_test<Integer> elem1; > generic_test<Double> elem2; > // generic_test<int> elem0; // * > } > } > > I mam pytania: > > 1. Dlaczego nie działa linijka oznaczona "// *", gdzie w specyfikacji jest > to > wytłumaczone, jasne jest dla mnie, że typ int nie daje referencji i to > pewnie > nie będzie działać dla żadnego POD'a. Ale gdzie to jest napisane w opisie > języka, aby poczytać szerzej na ten temat. Czy można liczyć na jakieś > "boxingi" jeżeli ktoś poda double zamiast Double w kontekście klas > generycznych?
Zaczynajac od konca, podajac double do typu sparametryzowanego jako Double zadziala autoboxing. Typy generyczne mozna parametryzowac tylko nazwami klas.
> 2. Jak zrobic specjalizację dla różnych typów. Chodzi mi o sytuację, że > jeżeli > mam typ T który jest czymś ala macierz to czasem doniego jest dostęp > poprzez > np. get(i,j), czasem inaczej a zatem chciałbym mieć generyczny wraper do > pobierania elementów z np. macierzy. Co ogólnie jest ważne jeżeli kod dla > poszczególnych typów jest inny.
Nie rozumiem pytania.
greg
Seweryn =?ISO-8859-2?Q?Habdank=2DWojew=F3dzki?= - 05-04-2006 00:04
Witam
Grzegorz Głowaty wrote:
> Zaczynajac od konca, podajac double do typu sparametryzowanego jako Double > zadziala autoboxing.
Ok.
> Typy generyczne mozna parametryzowac tylko nazwami klas.
Aha. A wiesz gdzie to jest wyspecyfikowane? Jak nie wiesz to nie szukaj.
>> 2. Jak zrobic specjalizację dla różnych typów. Chodzi mi o sytuację, że >> jeżeli >> mam typ T który jest czymś ala macierz to czasem doniego jest dostęp >> poprzez >> np. get(i,j), czasem inaczej a zatem chciałbym mieć generyczny wraper do >> pobierania elementów z np. macierzy. Co ogólnie jest ważne jeżeli kod dla >> poszczególnych typów jest inny. > > Nie rozumiem pytania.
Załóżmy, że jak było poprzednio:
public class generic_test<T> {
public T elem;
public generic_test(T elem) { System.out.println("Something"); // * do_something_on_Double(); // ** do_something_completely_else_on_Integer(); this.elem = elem; } }
Tyle, że "Something" chcę mieć inne dla Double inne dla Integer. Albo linijki poniżej chcę mieć różne czyli dla Double uruchamiam // * a dla Integer // *.
Chyba że to tylko mogę zrobić poprzez ręczne sprawdzanie typu?
Pozdrawiam i dziękuję za zainteresowanie.
--
|\/\/| Seweryn Habdank-Wojewódzki `\/\/
Piotr Kobzda - 05-04-2006 00:04
Seweryn Habdank-Wojewódzki wrote:
>>Typy generyczne mozna parametryzowac tylko nazwami klas. > > Aha. A wiesz gdzie to jest wyspecyfikowane? Jak nie wiesz to nie szukaj.
JLS3 4.4.
> > >>>2. Jak zrobic specjalizację dla różnych typów. Chodzi mi o sytuację, że >>>jeżeli >>>mam typ T który jest czymś ala macierz to czasem doniego jest dostęp >>>poprzez >>>np. get(i,j), czasem inaczej a zatem chciałbym mieć generyczny wraper do >>>pobierania elementów z np. macierzy. Co ogólnie jest ważne jeżeli kod dla >>>poszczególnych typów jest inny. >> >>Nie rozumiem pytania. > > > Załóżmy, że jak było poprzednio: > > public class generic_test<T> { > > public T elem; > > public generic_test(T elem) { > System.out.println("Something"); > // * do_something_on_Double(); > // ** do_something_completely_else_on_Integer(); > this.elem = elem; > } > } > > Tyle, że "Something" chcę mieć inne dla Double inne dla Integer. Albo linijki > poniżej chcę mieć różne czyli dla Double uruchamiam // * a dla Integer // *.
W Javie obowiązuje tzw. wymazywanie typów generycznych (type erasure) przez co kod generyczny nie wie jakim konkretnie typem został sparametryzowany.
> > Chyba że to tylko mogę zrobić poprzez ręczne sprawdzanie typu?
Tak. Twój przykład mógłby wyglądać tak:
public class GenericTest<T> {
public T elem;
public GenericTest(T elem) { System.out.println("Something"); if (Double.class.isInstance(elem)) { // * do_something_on_Double(); } else if (Integer.class.isInstance(elem)) { // ** do_something_completely_else_on_Integer(); } this.elem = elem; } }
Sposób ogólny, to jawnie przekazać klasie generycznej typu parametru jakim została sparametryzowana (czyli np. instancję Class<T>), co jednak w Twoim przykładzie nie wydaje się konieczne.
PS. Stosuj właściwie Javie konwencje nazewnictwa.
piotr
Seweryn =?ISO-8859-2?Q?Habdank=2DWojew=F3dzki?= - 05-04-2006 00:04
Witam
Piotr Kobzda wrote:
> JLS3 4.4.
Dziękuję to jest bardzo dobra odpowiedź.
> W Javie obowiązuje tzw. wymazywanie typów generycznych (type erasure) > przez co kod generyczny nie wie jakim konkretnie typem został > sparametryzowany.
Rozumiem.
>> Chyba że to tylko mogę zrobić poprzez ręczne sprawdzanie typu? > > Tak. Twój przykład mógłby wyglądać tak: > > public class GenericTest<T> { > > public T elem; > > public GenericTest(T elem) { > System.out.println("Something"); > if (Double.class.isInstance(elem)) { > // * do_something_on_Double(); > } else if (Integer.class.isInstance(elem)) { > // ** do_something_completely_else_on_Integer(); > } > this.elem = elem; > } > }
Czyli tak jak myślałem ręczne sprawdzenie typu.
> Sposób ogólny, to jawnie przekazać klasie generycznej typu parametru > jakim została sparametryzowana (czyli np. instancję Class<T>), co jednak > w Twoim przykładzie nie wydaje się konieczne.
W tym oczywiście, że nie, ale projektuję coś cięższego niż klasę generyczną dla Integer i Double, więc nie wiem czy i Class<T> nie będę używał.
> PS. Stosuj właściwie Javie konwencje nazewnictwa.
Czy masz na myśli GenericTest vs. generic_test?
Tak, stosuję w programach, ale jakoś tutaj pisałem szybko i przez to, że teraz dużo koduje w C++ napisałem w notacji z C++.
Nota bene jest mocna ekipa ludzi, którzy w C++ używają notacji Javy - IMHO to jest kwestia przyzwyczajeń i ustaleń w grupie programistów, oczywiście w Javie SUN narzuca pewną konwencję, której nie krytykuję, bo upodobań się nie krytykuje.
Chyba, że chodzi o co innego, to prosze mnie oświecić.
Pozdrawiam.
--
|\/\/| Seweryn Habdank-Wojewódzki `\/\/
Brzezi - 05-04-2006 00:04
wto, 04 kwi 2006 o 12:04 GMT, Seweryn Habdank-Wojewódzki napisał(a):
> Czyli tak jak myślałem ręczne sprawdzenie typu.
Tego nie da sie obejsc, bo niby jak? musisz wiedziec jaki typ jest uzywany, i zaleznie od niego "decydowac"
jedyna wariacja metody Piotra jaka jeszcze widze, to modyfikacja tego do wzorca Factory, robisz fabryke, za jej pomoca podajac typ, budujesz wyspecjalizowana klase...
Pozdrawiam Brzezi -- [ E-mail: brzezi@enter.net.pl ][ ] [ Ekg: #3781111 ][ ] [ LinuxUser: #249916 ][ ]
Seweryn =?ISO-8859-2?Q?Habdank=2DWojew=F3dzki?= - 05-04-2006 00:04
Witam
Brzezi wrote:
> Tego nie da sie obejsc, bo niby jak? musisz wiedziec jaki typ jest uzywany, > i zaleznie od niego "decydowac"
Tak tylko pytałem bo w C++ da się to inaczej zrobić, więc wolałem zapytać i upewnić się.
> jedyna wariacja metody Piotra jaka jeszcze widze, to modyfikacja tego do > wzorca Factory, robisz fabryke, za jej pomoca podajac typ, budujesz > wyspecjalizowana klase...
Masz rację, tylko, że Abstract Factory ma jedną wadę potrzebuje tworzyć objekty mające wspólną klasę bazową, a to jest dla mnie kłopotliwe, bo wymusiłoby to tworzenie niezbyt rozsądnego drzewa klas.
Pozdrawiam.
--
|\/\/| Seweryn Habdank-Wojewódzki `\/\/
Brzezi - 05-04-2006 00:04
wto, 04 kwi 2006 o 17:12 GMT, Seweryn Habdank-Wojewódzki napisał(a):
>> Tego nie da sie obejsc, bo niby jak? musisz wiedziec jaki typ jest uzywany, >> i zaleznie od niego "decydowac" > Tak tylko pytałem bo w C++ da się to inaczej zrobić, więc wolałem zapytać i > upewnić się.
a mozesz podac przyklad? tak z ciekawosci pytam co masz na mysli...
>> jedyna wariacja metody Piotra jaka jeszcze widze, to modyfikacja tego do >> wzorca Factory, robisz fabryke, za jej pomoca podajac typ, budujesz >> wyspecjalizowana klase... > > Masz rację, tylko, że Abstract Factory ma jedną wadę potrzebuje tworzyć objekty > mające wspólną klasę bazową, a to jest dla mnie kłopotliwe, bo wymusiłoby to > tworzenie niezbyt rozsądnego drzewa klas.
Mowilem ogolnie o Fabryce, nie wyszczegolnilem tam Abstract Factory, zasugerowalem tylko ogolna mysl :)
Pozdrawiam Brzezi -- [ E-mail: brzezi@enter.net.pl ][ brzezi:~# uptime ] [ Ekg: #3781111 ][ 17:16:10 up 2 days, 23:44, 1 user, ] [ LinuxUser: #249916 ][ load average: 1.45, 1.25, 1.17 ]
Seweryn =?ISO-8859-2?Q?Habdank=2DWojew=F3dzki?= - 05-04-2006 00:04
Witam
Brzezi wrote:
> wto, 04 kwi 2006 o 17:12 GMT, Seweryn Habdank-Wojewódzki napisał(a): >> Tak tylko pytałem bo w C++ da się to inaczej zrobić, więc wolałem zapytać i >> upewnić się. > > a mozesz podac przyklad? tak z ciekawosci pytam co masz na mysli...
przykład problemu:
//ładniej jest zrobić z seterami i geterami tak jak w opisie generyków u SUN'a, //ale nie chce mi się pisać. public class Pair<F, S> { public F first; public S second; }
public Kontener < ElementType, IndexType > { public ElementType getElement ( IndexType index ) { //tutaj muszę rozpoznawać IndeksType załóżmy, //że mamy Integer i Pair<Integer,Integer> //Ale kiedy tego jest więcej to kod staje się przyciężkawy }; }
Wersja w C++
template<typename F, typename S> struct Pair { F first; S second; }
//działanie domyślne - można też wsadzić do środka rozpoznawanie typów w połączeniu z działaniem domyślnym, //ale można inaczej jak niżej typename < ElementType, IndexType > struct Kontener { ElementType getElement ( IndexType index )//tu może być ";" //albo w "{}" domyślne działanie }
//specjalizacja szablonu dla indeksu Integer template < typename ElementType > struct Kontener < ElementType, Integer> { ElementType getElement ( Integer index ) { //funkcjonalność dla Integer } }
//specjalizacja szablonu dla indeksu Pair<Integer,Integer> template < typename ElementType > struct Kontener < ElementType, Pair<Integer,Integer > > { ElementType getElement ( Pair<Integer,Integer > index ){ //funkcjonalność dla Pair<Integer, Integer> } }
Jeśli w kodzie będą specjalizacje jak tutaj działanie domyślne będzie "nadpisane", klasa zostanie przeładowana ze względu na typy. To powoduje, że jeżeli nie znam się na jakims indeksie to nie muszę jego uwzględniać w swojej klasie a jak ktoś uzna to za stosowne sam sobie może go dopisać.
To jest prościutki przykład i na pewno można to zrobić na tysiąc innych sposobów, gorzej jest kiedy zaczynamy iść pod górę i zamiast Integer i Pair<Integer,Integer> mamy jakieś pogmatwane kontenery np. Hashtable< ElementType, ArrayList < ElementType > >. Przyczym zarówno Hashtable może być innym kontenerem jak i ArrayList może być czyś innym. I ten wewnętrzny if zrobi się koszmarny, choć pewnie da się go rozczłonkować, na podprzypadki i funkcjonalnośc powyżucac do innych klas.
Pozdrawiam.
--
|\/\/| Seweryn Habdank-Wojewódzki `\/\/
Piotr Lipski - 11-04-2006 00:24
Czy poniższy kod jest tym co chciałeś osiągnąć?
PL
public class Container<E, I extends Index<E, I>> { public static void main(String[] args) throws Exception { { Container<String, SimpleIndex<String>> h = Container(); h.getElement(new SimpleIndex<String>()); }
{ Container<Integer, PairIndex<Integer>> h = Container(); h.getElement(new PairIndex<Integer>()); } }
E getElement(I index) { return index.accept(this); }
static <E, I extends Index<E, I>> Container<E, I> Container() { return new Container<E, I>(); }
E get(SimpleIndex<E> index) { System.out.println("SimpleIndex<E>"); return null; }
E get(PairIndex<E> index) { System.out.println("PairIndex<E>"); return null; } }
interface Index<E, I extends Index<E, I>> { public E accept(Container<E, I> h); }
class SimpleIndex<E> implements Index<E, SimpleIndex<E>> { public E accept(Container<E, SimpleIndex<E>> h) { return h.get(this); }; }
class PairIndex<E> implements Index<E, PairIndex<E>> { public E accept(Container<E, PairIndex<E>> h) { return h.get(this); }; }
Seweryn =?ISO-8859-2?Q?Habdank=2DWojew=F3dzki?= - 12-04-2006 00:37
Witam
Piotr Lipski wrote:
> Czy poniższy kod jest tym co chciałeś osiągnąć?
Jeszcze nie wiem, ale dziękuję bardzo za całkiem zgrabyny kawałek kodu.
Pozdrawiam.
--
|\/\/| Seweryn Habdank-Wojewódzki `\/\/
Piotr Kobzda - 16-04-2006 01:01
Seweryn Habdank-Wojewódzki wrote:
> Piotr Lipski wrote: > >>Czy poniższy kod jest tym co chciałeś osiągnąć? > > Jeszcze nie wiem, ale dziękuję bardzo za całkiem zgrabyny kawałek kodu.
A może poniższe bardziej Twym potrzebom odpowiada?
piotr
public class Container<E, I> {
public static void main(String[] args) { { Container<String, Integer> c = Container.newIntegerIndexedInstance(); c.getElement(3); } { Container<String, Pair<Long, Short>> c = Container.newPairIndexedInstance(); c.getElement(new Pair<Long, Short>()); } }
public interface IndexedAccess<E, I> { E get(Container<E, I> container, I index); }
private IndexedAccess<E, I> ia;
public Container(IndexedAccess<E, I> ia) { this.ia = ia; }
public E getElement(I index) { return ia.get(this, index); }
public static <E> Container<E, Integer> newIntegerIndexedInstance() { return new Container<E, Integer>( new IndexedAccess<E, Integer>() { public E get(Container<E, Integer> container, Integer index) { System.out.println(container +".getElement("+ index + ")"); return null; } }); }
public static <E, F, S> Container<E, Pair<F, S>> newPairIndexedInstance() { return new Container<E, Pair<F, S>>( new IndexedAccess<E, Pair<F, S>>() { public E get(Container<E, Pair<F, S>> container, Pair<F, S> index) { System.out.println(container +".getElement("+ index + ")"); return null; } }); }
}
zanotowane.pldoc.pisz.plpdf.pisz.pleffulla.pev.pl
|
[MSSQL2000] Problem z =?ISO-8859-2?Q?tabel=B1/indeksem/zapytanie?==?ISO-8859-2?Q?m_czy_b=B3=B1d_w_bazie_danych=2E=2E=2E?=
mysql i mysql-front, problem
String line; if (line=="cos"){...}....problem
Problemy z =?ISO-8859-2?Q?instalacj=B1_PostgreSQL_na_syste?==?ISO-8859-2?Q?mach_Windows?=
[postgres] Problem z =?ISO-8859-2?Q?zmian=B1_struktury_i_z?==?ISO-8859-2?Q?ale=BFno=B6ciami=2E?=
[oracle] =?ISO-8859-2?Q?zmia=BFd=BFony_przez_problem=3A_za?==?ISO-8859-2?Q?pytanie_do_hierarchi?=
Problem z wartościami w MySQL :( [ MySQL and ASP and VBScript ]
[PGSQL] czy ktos mial problemy z initdb pgsql 8.1 ?
[MySQL] Problem z zapisem danych w bazie danych
Problem z mysql - can't connect to MySQL/nietypowo...
zanotowane.pldoc.pisz.plpdf.pisz.pltejsza.htw.pl
Cytat
Decede mihi sole - nie zasłaniaj mi słonca. Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści Hoc fac - tak czyń. A tergo - od tyłu; z tyłu. I czarne włosy posiwieją. Safona |
|