[ djura1 @ 19.08.2004. 20:01 ] @
Ovo je verovatno vrlo prosto, ali nikako ne mogu da provalim kako se radi.

Iz jednog metoda klase treba da vratim shallow copy polja te klase koje je tipa List.
Pokusao sam ovako:
Code:

return (List)polje.clone();


Ali stalno dobijam gresku "clone() has protected access in java.lang.Object".
U dokumentaciji sam procitao ovo:
Citat:

By convention, the returned object should be obtained by calling super.clone

ali ne mogu da provalim kako se to radi, ako je to uopste to. Ako neko moze da da neki primer...
[ -zombie- @ 19.08.2004. 21:50 ] @
nije mi baš jasno.. imaš polje tipa List? šta je to List? jel to javin interfejs (kolekcija) java.util.List, ili neka tvoja klasa?

u svakom slučaju, klasa objekta koji želiš da kloniraš mora zadovoljavati dva uslova:
1) da implementira interfejs Cloneable, i
2) da ima overridovan clone() method, jer je Object.clone() protected, i ne može se pozivati direktno..

znači, u tvojoj klasi moraš da imaš bar ovako nešto..

Code:
public Object clone() {
    return super.clone();
}

[ djura1 @ 19.08.2004. 22:41 ] @
Da, u pitanju je java.util.List. Pokusacu malo bolje da objasnim

Code:

class X{
    List list=new ArrayList();
    
    public List metod(){
         return (List)list.clone();
    }
}


E sad, kad uradim ovako, dobijem poruku "clone() has protected access in java.lang.Object". Kako da napravim kopiju liste koristeci clone()?
[ -zombie- @ 19.08.2004. 23:09 ] @
moraš da odradiš ovako nešto, tj da castuješ listu nazad u ArrayList koja implementira clone() metod. interfejs List nema tu metodu, pa se svede na Object koji je ima, ali je u njoj clone() protected.

Code:
public List metod() {
     return (List) ((ArrayList) list).clone();
}


ovo će tebi verovatno završiti posao, ali imaj na umu da je upcastovanje često znak loše isprojektovanog koda..

// edit: eto, dok ja napišem i objasnim.. ;)
[ djura1 @ 20.08.2004. 07:14 ] @
Da, ovo sljaka. Hvala na pomoci.
[ BlueIce @ 20.08.2004. 08:13 ] @
-zombie-, pošto tek počinjem da učim Javu, da li bi mogao da mi pojasniš zašto je upcasting loš, i kako je ovo trebalo da se uradi?
Hvala!
[ veljaradenkovic @ 20.08.2004. 10:27 ] @
Upcasting je castovanje izvedene klase u generalniji bazni tip.

http://mindprod.com/jgloss/upcasting.html

Nikako ne mora da bude znak lose isprojektovanog softvera.

U konkretnom slucaju

Code:

class X{
    List list=new ArrayList();
    
    public List metod(){
         return ((List) ((ArrayList) list).clone());
    }
}


o drugim (boljim) resenjima se bez uvida u ostatak sistema ne moze govoriti.



[ BlueIce @ 20.08.2004. 12:32 ] @
Baš zato mi nije jasno zašto je to u ovom slučaju loše (a ispalo je da je upcasting baš ono što sam mislio da jeste), u ovom konkretnom primeru vidim samo neki performance/memory overhead, jer ako sam ja dobro shvatio onih nekoliko poglavlja iz Thinking in Java moglo je i ovako:
Code:
class X{
    List list=new ArrayList();
    
    public List metod(){
         ArrayList temp = list.clone(); //Ovo bi trebao da radi nad ArrayList, a ne List
         return ((List) temp);
    }
}

Jedino kada bi po meni sve ovo imalo smisla jeste da Java prvo izvrši cast pa tek onda pristupa metodi a ne obrnuto, da li ona tako zaista radi?
[ veljaradenkovic @ 20.08.2004. 13:46 ] @
Deklarisuci list kao java.util.List kazes da ce ovaj u bilo kom ternutku izvrsavanja programa, referencirati objekt koji implementira interface List a to ne mora da bude ArrayList; te nad ovim mozes izvrsavati samo ono deklarisano u ovom interface-u (java.util.List).

Vidi, ArrayList ima metodu clone().
A
Code:
class Pera implements java.util.List{...}
nema jer je nismo implementirali.

Sad zamisli ovo; on je deklarisao varijablu list tipa List, kreirao novi objekat tipa ArrayList i dodelio ga varijabli list. Onda se izvrsi druga metoda (pre ove sporne) i kaze
Code:
list = new Pera();
kako ces sad da kloniras peru kad nece.

Da se java svodi na ovaj njegov primer neko bi pomislio da je javac glup i da tvoj neispravan kod treba da radi.

Nema tu nikakvog kastovanja. JAVA trazi odgovarajucu metodu na referenciranom objektu i poziva je.

Mozda da pogledas ovo http://max.hosting.ru/docs/Java/

Knjiga Abstract Data Types in Java malo je starija ali ima ovo sve.


[ BlueIce @ 20.08.2004. 20:15 ] @
HTTP 403 za onaj link koji si dao :(

PS: Sad sem tek video kakvu sam glupost napisao u onoj liniji sa komentarom, jer ako:
Code:
List list=new ArrayList();

bez obzira što je inicijalizovan preko new ArrayList() to nema veze jer će kreirani objekat i referenca na isti biti tipa List što je u stvar interfejs, da li sam u pravu?
[ -zombie- @ 20.08.2004. 20:27 ] @
Citat:
veljaradenkovic:
Upcasting je castovanje izvedene klase u generalniji bazni tip.

Nikako ne mora da bude znak lose isprojektovanog softvera.


naravno.. lapsus lingua, mislio sam na downcast, tj castovanje reference generalnog (baznog) tipa, nazad u izvedenu klasu..

znači, ovo nije primer upcasta već downcasta, pošto klasa ArrayList implementira (u javinom žargonu) interfejs List, odnosno nasleđuje List (u klasičnom OOP/C++ žargonu). zato se može reći da se pri kreiranju i dodeljivanju List lista = new ArrayList(); radi upcast, a u onoj metodi radi downcast..

(a downcast već može da bude znak..)

Citat:
BlueIce:
-zombie-, pošto tek počinjem da učim Javu, da li bi mogao da mi pojasniš zašto je upcasting loš, i kako je ovo trebalo da se uradi?


greška (vidi gore), a za ovaj konkretan slučaj sam rekao da je verovatno ok, ali da downcasting često može da znači loše projektovanje..

tj, u ovom konkretnom slučaju downcast poništava poJentu korišćenja List interfejsa. interfejs se koristi (između ostalog) da bi kasnije u razvoju projekta, kada otkriješ da je recimo jedna klasa usko grlo, možeš zameniti bilo kojom drugom klasom koja implementira isti interfejs, a da ne menjaš ni jednu liniju ostatka koda..

nasuprot tome, ako bi u ovom primeru poželeo da umesto ArrayList koristš Vector, morao bi da promeniš i liniju gde si listu downcastovao u ArrayList, jer lista više nije tog tipa..

rešenje bi možda bilo (pomalo napamet, bez uvida u ostatak projekta) da se napravi novi interfejst CloneableList koji bi nasledio i List i Cloneable, i plus dodao javni metod clone() (pošto Cloneable ne sadrži taj metod, već se ponaša čisto kao "flag").

Citat:
veljaradenkovic:
Sad zamisli ovo; on je deklarisao varijablu list tipa List, kreirao novi objekat tipa ArrayList i dodelio ga varijabli list. Onda se izvrsi druga metoda (pre ove sporne) i kaze list = new Pera(); kako ces sad da kloniras peru kad nece.


upravo je to jedan od primera zašto downcast može biti znak lošeg dizajna..

Citat:
BlueIce:
bez obzira što je inicijalizovan preko new ArrayList() to nema veze jer će kreirani objekat i referenca na isti biti tipa List što je u stvar interfejs, da li sam u pravu?


delimično. kreirani objekat može biti "tipa" samo neke klase (koja implementira neki interfejs), a ne samog interfejsa. sa druge strane, referenca, odnosno varijabla koja pokazuje na taj objekat može i hoće biti tipa List.
[ veljaradenkovic @ 20.08.2004. 22:06 ] @
Blue Ice:

http://max.hosting.ru/

Evo ga prepravio sam ovaj radi. Knjiga ti je prva po redu.

U medjuvremenu setio sam se mozda i bolje napisanog (ispod). Nadji Abstract data types.

http://www.brpreiss.com/books/opus5
[ BlueIce @ 21.08.2004. 07:57 ] @
Hvala, -zombie- i veljaradenkovic, sad je jasnije.
PS: Link je sada ok, jedva čekam da se vratim na fax da se bacim na download :)