|
[ boris Dj.bl @ 06.07.2008. 19:01 ] @
| Imam jedno kratko pitanje.
Kako se definise i koristi niz objekata u Javi.
Evo jedan mali primjer.
Code:
public class Automobil {
private boolean radi;
public void upali() { radi = true; }
public void ugasi() { radi = false; }
public boolean getradi() { return radi; }
}
Code:
class Main {
public static void main(String args[]) {
int i=5;
int n[]=new int[10]; n[2]=25;
Automobil a= new Automobil();
a.upali();
//Automobil c[]=new Automobil[3];
//c[0].upali();
System.out.println(i + " " + n[2]+ " " + a.getradi() + " ");
//System.out.println(i + " " + n[2]+ " " + a.getradi() + " " + c[0].getradi());
}
}
Klasa je Automobil koja ima jedan atribut radi tipa boolean.
U main-u sam koristi i niz int-ova (n[]) sto radi, koristio sam i sam objekat (a) sto takodje radi, al kad hocu niz tih objekata (c[]) to vec ne radi.
Kako se onda pisu nizovi objekata.
Moze i na ovom primjeru.
Ako se ovako kompajlira radi i izlaz je:
a kad se skinu znakovi za komentare (//) moze se opet kompajlirati al pri pokretanju izbaci ovu gresku:
Citat: Exception in thread "main" java.lang.NullPointerException
at Main.main(Main.java:12)
Znam da je int osnovni tip i da mu se direktno pristupa, dok se objektima pristupa preko referenci al i dalje ne znam kako da napravim niz objekata, tj niz referenci a svaka referenca da pokazuje na svoj objekat. |
[ bags @ 06.07.2008. 19:22 ] @
Nisi inicijalizovao objekte u nizu tj. imas samo prazan niz objekata.
Mozes recimo uraditi:
Code:
c[0] =a;
Ili se igrati sa foreach petljom.
Danas se nizovi retko koriste.Pogledaj kako se koriste kolekcije u javi:
http://java.sun.com/docs/books...ons/implementations/index.html
[ boris Dj.bl @ 06.07.2008. 22:59 ] @
Vec sam nasao odgovor.
Ovo je zapravo sto je meni trebalo.
Code:
class Main {
public static void main(String args[]) {
Automobil c[]=new Automobil[3];
int i;
for(i=0; i<c.length; i++)
c[i]=new Automobil();
c[0].upali();
System.out.println( "c[0]= "+c[0].getradi() +"\n" +"c[1]= " + c[1].getradi() );
}
}
Pa nek se nadje ako jos nekom zatreba.
U svakom slucaju hvala.
A nije bitno sto se nizovi inace malo koriste jer meni sad oni iskljucivo trebaju pa moram i nauciti da ih koristim.
[ boris Dj.bl @ 07.07.2008. 23:06 ] @
Moze jos jedno pitanje vezano za istu klasu Auto.
Neka je ovo main
Code:
class Main {
public static void main(String args[]){
Automobil a = new Automobil(), b = new Automobil(), c;
a.upali();
b.upali();
boolean t; t=a.equals(b);
//c=a.clone();;
System.out.println(t);
}
}
Ispis je
E sad mene zanima zasto je false a ne true.
Naime da je a==b onda bi samo provjeravao da li a i b pokazuju na isti objekat pa ako da vraca true, inace false.
Ali posto je a.equals(b) to bi trebalo da provjerava da li su sami objekti jednaki tj da li imaju isti sadrzaj.
Posto oba objeka imaju samo jedan tip boolean koji je u oba u tom trenutku true znaci da bi rezultat a.equals(b) trebao biti true???
Ili se varam.
Znam da bi ja mogao napraviti svoju metodu koja provjerava sadrzaj al u cemu je onda korist te metode equals koje se nasljedjuje iz osnovne klase Object.
I druga stvar.
Iz osnovne klase Object se nasledjuje i metoda clone koja pravi kopiju objekta.
Zasto onda kad se skinu // program izbacuje sledecu gresku?
Citat:
Main.java:10: clone() has protected access in java.lang.Object
c=a.clone();;
^
Main.java:10: incompatible types
found : java.lang.Object
required: Automobil
c=a.clone();;
^
2 errors
Tj kako da napravim pravu kopiju od a i da je dodjelim c.
[ boris Dj.bl @ 08.07.2008. 21:57 ] @
Ovdje neka pitanja ne vrijedi postavljati, bar u vezi JAVE.
Odgovora ni za lijeka.
Dok se sam ne snadjem nema pomoci.
U svakom slucaju skontao sam da funkcija equals radi isto sto i == tj provjerava da li reference pokazuju na isti objekat a ne porede sadrzaj kao sto sam ja mislio.
Posto sam ja htio poredjenje sadrzaja redefinisao sam ovu funkciju.
Sto se tice metode clone() i dalje ne znam tacno zasto c=a.clone() ne radi al i tu sam problem rjesio redefinisanjem metode.
Ovako to izgleda u klasi.
Code:
public class Automobil {
protected boolean radi;
public void upali() { radi = true; }
public void ugasi() { radi = false; }
public boolean getradi() { return radi; }
public boolean equals(Automobil s) { if(radi==s.radi) return true; else return false; }
public Automobil clone() { Automobil p=new Automobil(); p.radi=radi; return p;}
}
[ bags @ 08.07.2008. 22:04 ] @
Da bi ti radili clone i equal moras implementirati interfejse Cloneable i Comparable. ;)
[ _Abraxas @ 08.07.2008. 23:11 ] @
Citat: bags: Da bi ti radili clone i equal moras implementirati interfejse Cloneable i Comparable. ;)
Nisam bas siguran za ovo. Ukoliko bi samo implementirali interface Cloneable, to samo znaci da ne bi dobili izuzetak java.lang.CloneNotSupportedException, a ne i da mozemo da koristimo metodu clone() klase Object (barem tako mislim). Da bismo koristili tu metodu, treba da u svojoj klasi Automobil dodas sledeci kod:
Code:
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
Sto se tice metode equals(), ona je na nivou klase Object implementirana kao i znak poredjenja (==), znaci poredi reference, a ne sadrzaje objekata. Da bi metoda equals() radila ono sto ti zelis, tj. poredila sadrzaj, opet je moras overridovati. Ja sam napisao sledeci kod:
Code:
@Override
public boolean equals(Object obj) {
if(this.radi == ((Automobil)obj).radi)
return true;
else
return false;
}
Naravno, ti mozes imati i svoju metodu, recimo kloniraj() u kojoj ces samo pozvati metodu clone() klase Object. Ili metodu uporedi() u kojoj ces raditi ono sto sam ja radio u overridovanoj metodi equals().
Pozdrav.
[ bags @ 08.07.2008. 23:33 ] @
_Abraxas, u pravu si naravno.
U zelji da sto prije napisem odgovor, grubo sam se za*ebao. :)
[ boris Dj.bl @ 09.07.2008. 16:05 ] @
Ok, sad smo to razjasnili.
Posto vidim da se ipak nadju odgovori evo jos jedno kratko pitanje.
Da li se moze u JAVI, i kako, pozvati metoda iz nadklase ako je izvedenoj klasi redefinisana.
Ovako je to u C++.
Code:
class Aklasa {
public void met(){...}
}
class Bklasa : public Aklasa {
public void met(){...}
}
main(){
Bklasa b1;
b1.Aklasa::met();
}
Code:
class Aklasa {
public void met(){...}
}
class Bklasa extends Aklasa {
public void met(){...}
}
public static void main(String args[]) {
Bklasa b1=new Bklasa();
b1.???met();
}
U JAVI ne moze Aklasa:: , moze li nesto drugo?
[ Nikola Poša @ 09.07.2008. 19:19 ] @
U Javi postoji neshto shto se zove dinamichko razreshavanje, ili polimorfizam, a to otprilike na ovom tvom donjem primeru znachi sledece:
poshto si u main-u napravio objekat klase "BKlasa", i preko reference b1 pozivash metod "met()", izvrshice se metod "met()" iz klase "BKlasa". A da bi pozvao taj isti metod u ovoj prvoj klasi, jednostavno napravish objekat te klase i preko odredjene reference pozovesh zheljeni metod. Nadam se da ti je sad malo jasnije...
[ boris Dj.bl @ 09.07.2008. 19:51 ] @
Znam ja sta je polimorfizam.
I dok se u C++ on za neke stvari mora implementirati u JAVI je to tako po default-u.
Konkretno ako sam refefinisao met() u Bklasa.
I ako kazem b1.met() pozvace se metoda iz Bklasa.
A ako imam pointer Aklasa koji pokazuje na objekat Bklasa Aklasa *ap; Bklasa b1; ap=&b1 i kazem ap->met() pozvace se metoda iz Aklasa.
Posto ovo obicno nije ono sto nama odgovara moramo u Aklasa definisati metodu kao virtuelnu tj virtual void met() {...} pa ce se sad pri pozivu ap->met() pozvati metoda iz Bklasa.
U JAVI ako je Aklasa ar=new Bklasa(); i pri pozivu ar.met() pozivace se metoda iz Bklasa, sto opet i treba, jer su u JAVI sve metode po defalut-u virtuelne.
Ne moramo mi eksplicitno navoditi.
Normalno da ce se nad objektom Aklase uvijek izvrsiti metoda iz Aklasa.
Tako da ako sad pogledamo oba slucaja u C++ b1.met() i ap->met() pozivaju se metode iz Bklasa sto i treba.
Medjutim ja imam mogucnost da nad ovim objektima Bklase pozovem met() iz Aklasa sto se radi na sledeci nacin
b1.Aklasa::met() i ap->Aklasa::met()
Ovo mozda i nema puno logike raditi al to nije sad poenta vec cisto tehnicke mogucnosti.
Prema tome da li je ovako nesto moguce u JAVI, znaci da se nad objektom neke izvedene klase koja ima redefinisanu medotu met() eksplicitno pozove ona "stara" metoda iz roditeljske klase.
I ako je moguce kao se to radi?
Mada kako se upoznajem sa JAVOM cini mi se da ovo nije moguce, jer za razliku od C++ gdje je sve dozvoljeno a na programeru je da odluci sta je najbolje i najispravnije u Javi je dozvoljeno samo ono sto je zaista neophodno, a ova mogucnost C++ a mi ne izgleda neophodna.
[ Nikola Poša @ 09.07.2008. 20:19 ] @
Citat: boris Dj.bl:
Prema tome da li je ovako nesto moguce u JAVI, znaci da se nad objektom neke izvedene klase koja ima redefinisanu medotu met() eksplicitno pozove ona "stara" metoda iz roditeljske klase.
I ako je moguce kao se to radi?
Koliko ja znam, tako neshto nije moguce. Mozhda i postoji neki nachin, ali trenutno mi nishta ne pada napamet. A i to shto kazhesh, mogucnost za to u C++ i nije od tolikog znachaja. U Javi nema pokazivacha, i stvari se, barem po mom mishljenju, reshavaju na dosta logichniji nachin...
[ zigizig @ 09.07.2008. 21:19 ] @
How can I call an overridden method in the superclass?
A: To call a superclass method that has been overridden in a subclass, you must either call the method directly through a superclass instance, or use the super prefix in the subclass itself. From the point of the view of the subclass, the super prefix provides an explicit reference to the superclass' implementation of the method.
Code:
// From subclass
super.overriddenMethod();
Bitno je samo razdvojiti pojam reference od objekta.
Znaci ne može direktno preko reference objekta Bklasa da se pozove metoda iz Aklasa koja je overriden u Bklasa, ali moze u Bklasa da se napravi metoda metSuper() koja poziva super.met() i onda ce se pozivom metSuper() izvrsiti i met() iz Aklasa!
A moze i nesto ovako mada :)
Code:
class Aklasa {
static int a = 0;
public void met() {
System.out.println("aklasa " + a);
a++;
}
}
Code:
class Bklasa extends Aklasa {
int b = 2;
public void met() {
System.out.println("bklasa " + b);
}
public static void main(String args[]) throws SecurityException,
NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Bklasa b1 = new Bklasa();
b1.met();
Class c = b1.getClass();
Method m = c.getSuperclass().getMethod("met", new Class[0]);
m.invoke(new Aklasa(), null);
System.out.println("b1.a = " + b1.a);
m.invoke(new Aklasa(), null);
System.out.println("b1.a = " + b1.a);
}
[ boris Dj.bl @ 09.07.2008. 23:37 ] @
Hvala zigizig.
To sa super funkcionise, jednostavno je a i logicno.
npr
Code:
class Bklasa extends Aklasa {
int b = 2;
public void met() {
System.out.println("bklasa " + b);
}
public void metSuper() {
super.met();
}
public static void main(String args[]) {
Bklasa b1 = new Bklasa();
b1.met();
b1.metSuper();
}
}
Sto se tice tvog drugog nacina moram priznati da niti mi je jasan a i pri kompajliranju izbacuje neku gresku.
U svakom slucaju previse je komplikovan pa samim tim i nepotreban kad se to moze fino rjesiti koriscenjem super.
Jedino sto je jos upitno, sta ako imam gotove klase Aklasa i Bklasa bez koda pa ne mogu ni dodati metodu metSuper().
Kao rjesenje mi pada na pamet da naslijedim klasu Bklasa u neku BklasaIzv i da u njoj samo dodam funkciju metSuper() { super.super.met(); }
Al ovo ovako nece da se kompajlira. Da li je uopste ovo ovako moguce?
pozdrav
[Ovu poruku je menjao boris Dj.bl dana 10.07.2008. u 00:47 GMT+1]
[ boris Dj.bl @ 10.07.2008. 00:11 ] @
Sad nadjoh da ovo super.super.met() ipak nije moguce.
Razlog za to je da ako imam klase bez koda, tj da ih je neko dugi radio onda je on morao misliti da li da klijentu omoguci pritup nekoj metodi iz nad klase koju je on redefinisao.
Tako da je autor te klase trebao prakticno dodati metodu metSuper() ako je smatrao to iole potrebnim.
E sad mene i dalje zanima, onako hipoteticki, da li uopste postoji neki nacin za ovo ako nemam kod klase a autor nije dodao tu metodu.
Zigi da li funkcionise tvoj drugi metod?
[ _Abraxas @ 10.07.2008. 02:57 ] @
^Postoji drugi način, a on se zove kompozicija:
Code:
class C
{
public void met(A a)
{
a.met();
}
}
Iliti, ako je metoda met() mora da bude bez parametara:
Code:
class C
{
public void met()
{
A a = new A();
a.met();
}
}
[ del-boy @ 10.07.2008. 04:29 ] @
Citat:
Sad nadjoh da ovo super.super.met() ipak nije moguce.
Razlog za to je da ako imam klase bez koda, tj da ih je neko dugi radio onda je on morao misliti da li da klijentu omoguci pritup nekoj metodi iz nad klase koju je on redefinisao.
Tako da je autor te klase trebao prakticno dodati metodu metSuper() ako je smatrao to iole potrebnim.
E sad mene i dalje zanima, onako hipoteticki, da li uopste postoji neki nacin za ovo ako nemam kod klase a autor nije dodao tu metodu.
Zigi da li funkcionise tvoj drugi metod?
Mozes sam u toku izvrsavanja programa da menjas nivo pristupa metodama iz klasa koje koristis (bilo da imas njihov kod ili da nemas). Evo ti primer:
Code:
public class A {
private void echo() {
System.out.println("Iz klase A");
}
}
Code:
import java.lang.reflect.Method;
public class B {
public static void main(String args[]) {
try {
A a = new A();
Class c = a.getClass();
Method m = c.getDeclaredMethod("echo", new Class[0]);
m.setAccessible(true);
m.invoke(a);
}
catch (Exception e) { e.printStackTrace(); }
}
}
Primeti da iako je metoda echo u klasi A privatna pozvao sam je (na posredan nacin) i izvrsio iz klase B. Istu tehniku je zigizig upotrebio par postova iznad (refleksiju), samo sto nije imao primer menjanja nivoa pristupa.
[ zigizig @ 10.07.2008. 08:47 ] @
(dok sam pisao nisam video da je "del-boy" već dao dobar primer ali ni ovo neće da škodi ;)
Drago mi je da sam ti pomogao.
Inače onaj drugi način je više bio kao primer.
Vidiš, java ne dopušta da iz klase recimo Aklasa pristupiš privatnoj metodi ili variabli Bklasa.
Ali...(mislim da ovaj primer ima više smisla kada metode nisu overriden)... iz-google-aj malo o "java reflection". Ima dosta primera.
U principu refleksija ti dopušta da zaobiđeš skoro sve moguće zaštite u java jeziku.
Code:
class Aklasa {
static int a = 0;
private void metA() {
System.out.println("aklasa " + a);
a++;
}
}
Code:
class Bklasa extends Aklasa {
int b = 2;
private void metB() {
System.out.println("bklasa " + b);
}
}
Code:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Cklasa extends Bklasa {
int c = 3;
public void metC() {
System.out.println("cklasa " + c);
}
public static void main(String args[]) throws SecurityException,
NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Cklasa cklasa = new Cklasa();
cklasa.metC();// poziv met() iz Cklasa
// cklasa.metB(); // ovo nije dozvoljeno
Class c1 = cklasa.getClass().getSuperclass();
Method m = c1.getDeclaredMethod("metB", new Class[0]);
m.setAccessible(true);
m.invoke(cklasa, null);// poziv metB() iz Bklasa
m.setAccessible(false);
// cklasa.metA(); // ovo nije dozvoljeno
Method m2 = c1.getSuperclass().getDeclaredMethod("metA", new Class[0]);
m2.setAccessible(true);
m2.invoke(cklasa, null);// poziv metA() iz Aklasa
m2.setAccessible(false);
System.out.println("cklasa.a = " + cklasa.a);
}
}
[ boris Dj.bl @ 10.07.2008. 16:30 ] @
Abraxas kompozicija nije bas drugi nacin za pozivanje metode pretka nad potomkom.
Sve sto ova kompozicija radi je da se pri pozivanju neke metode instancira objekat pretka pa se nad njim pozove ta metoda al to nije poziv metode pretka nad potomkom.
Normalno trenutno smo na pretpostavci da je u klasi potomka redefinisana ta metoda i da nemamo kod tih klasa.
A sto se tice nivoa pristupa atributa i metoda i njihovih promjena ne vidim kakve on ima veze sa pozivanjem metode pretka nad potomkom.
Da se vratim na pocetak.
U C++ je to moguce na sledeci nacin
Code:
class Aklasa {
public void met(){...}
}
class Bklasa : public Aklasa {
public void met(){...}
}
main(){
Bklasa b1;
b1.Aklasa::met();
}
U JAVI se moze implementirati da radi isto ako imam kod B klase gdje cu dodati metSuper(){} u u njoj pozvati metodu pretka preko super, kao sto je zigi rekao.
Ako pak nemam kod klasa a metoda je redefinisana zakljucujem da to u Javi nije moguce, jer ne vidim da je iko nasao nacin za ovo.
[ _Abraxas @ 11.07.2008. 02:02 ] @
Citat: boris Dj.bl: Abraxas kompozicija nije bas drugi nacin za pozivanje metode pretka nad potomkom.
Sve sto ova kompozicija radi je da se pri pozivanju neke metode instancira objekat pretka pa se nad njim pozove ta metoda al to nije poziv metode pretka nad potomkom.
Ne, naravno da kompozicija generalno nije nacin poziva metode pretka (iako u specijalnim slucajevima moze biti :)). Ali rezultat poziva moje metode i tvojih je isti, odnosno isti je efekat, zar ne? Ja sam samo hteo da ukazem da postoje i drugi nacini, u smislu razmisljanja, da se rese neki problemi, tacnije ogranicenja jezika (ako ovo i predstavlja ogranicenje). :)
[ boris Dj.bl @ 11.07.2008. 09:33 ] @
Citat:
_Abraxas
Ne, naravno da kompozicija generalno nije nacin poziva metode pretka (iako u specijalnim slucajevima moze biti :)). Ali rezultat poziva moje metode i tvojih je isti, odnosno isti je efekat, zar ne? Ja sam samo hteo da ukazem da postoje i drugi nacini, u smislu razmisljanja, da se rese neki problemi, tacnije ogranicenja jezika (ako ovo i predstavlja ogranicenje). :)
U redu je, i drugi nacini su pozeljni, cisto edukativno, al ipak mislim da ni rezultat ovih poziva nije isti.
Jer koristenjem kompozicije ti hoces pozvati ovu funkciju ali nad lokalnim objektom A klase i nad njim ce se izvrsiti eventualna promjena dok poziv te metode nad objektom B klasa vrsi nad njim promjenu o cemu sam ja i govorio.
Mislim da smo sad sa ovim, i mojim prethodnim postom a i od ostalih, skoro sve razjasnili.
Tj sta je sve moguce prilikom nasledjivanja i na koje nacine.
Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|