objektno orijentisano programiranje

69
Objektno orijentisano programiranje Java, interfejsi

Upload: axl

Post on 16-Jan-2016

58 views

Category:

Documents


0 download

DESCRIPTION

Java, interfejsi. Objektno orijentisano programiranje. Određivanje klase objekta - nastavak. Iako se može koristiti metod forName() da bi se dobio Class objekat koji odgovara određenoj klasi ili interfejsu, postoji direktniji način - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Objektno orijentisano programiranje

Objektno orijentisano programiranje

Java, interfejsi

Page 2: Objektno orijentisano programiranje

Određivanje klase objekta - nastavak● Iako se može koristiti metod forName() da bi se dobio Class

objekat koji odgovara određenoj klasi ili interfejsu, postoji direktniji način

● Ako nadovežemo .class na ime proizvoljne klase, interfejsa ili primitivnog tipa, imamo referencu na Class objekat te klasenpr. java.lang.String.class referiše Class objekat za klasu String, dok Pas.class referiše Class objekat za klasu Pasint.class je Class objekat za primitivni tip int

● Ovo možda u ovom trenutku ne izgleda posebno značajno, ali treba ga imati na umu

Page 3: Objektno orijentisano programiranje

Određivanje klase objekta - nastavak● Pošto postoji samo po 1 Class objekat za svaku klasu ili

interfejs, klasa objekta se može testirati programski Zivotinja ljubimac;

može se proveriti da li referiše na objekat klase Pas na sledeći način:

if(ljubimac.getClass()==Pas.class) System.out.println(”To je pas!”);

● Ako ljubimac sadrži referencu na objekat potklase klase Pas, rezultat poređenja u if-u je false

● U Javi postoji operator instanceof koji radi skoro istu stvar, ali ne i potpuno istu

Page 4: Objektno orijentisano programiranje

Klasa Class

● Klasa Class nije obična klasa● To je primer generičkog tipa ( zapravo definiše

skup klasa)● Svaka klasa, interfejs, niz i primitivni tip koji

koristimo u programu biće predstavljen objektom jedinstvene klase iz skupa definisanog Class generičkim tipom

Page 5: Objektno orijentisano programiranje

Kopiranje objekata

● protected metod clone() koji je nasleđen od klase Object kreiraće novi objekat koji je kopija tekućeg objekta

● On će to uraditi jedino ako klasa objekta koji treba klonirati ukazuje da je kloniranje dopušteno, a to je slučaj kada klasa implementira interfejs Cloneable

● Metod clone() nasleđen od Object klonira objekat kreiranjem novog objekta istog tipa kao što je tekući objekat i postavljajući svako od polja novog objekta na istu vrednost koju ima odgovarajuće polje tekućeg objekta

Page 6: Objektno orijentisano programiranje

Kopiranje objekata

● Kada atributi tekućeg objekta referišu na objekte klasa, objekti na koje oni referišu se NE DUPLIRAJU prilikom kreiranja klona – samo se reference iskopiraju iz polja starog objekta u polja kloniranog objekta

● To tipično nije ono što želimo da se desi – i novi i stari objekat onda mogu menjati taj deljeni objekat na koji se referiše preko njihovih odgovarajućih atributa, bez registrovanja da se to dešava

Page 7: Objektno orijentisano programiranje

Kopiranje objekata

● Ako objekte klase treba klonirati, klasa mora implementirati Cloneable interfejs (implementiranje interfejsa obično uključuje implementiranje specifičnog skupa metoda )

● Sve što je potrebno da bi klasa implementirala ovaj interfejs jeste da se to deklariše u prvoj liniji definicije klase pomoću ključne reči implements:class Pas implements Cloneable{

// Detalji definicije klase ... } onda se objekti klase Pas mogu klonirati● primer: kloniranje

Page 8: Objektno orijentisano programiranje

Komentarisanje primera

● PasLjubimac objekat može se kreirati sa: PasLjubimac mojLjubimac = new PasLjubimac(”Maza”,”Mesanac”);● Ako želite istog takvog, možemo ga klonirati: PasLjubimac vasLjubimac = (PasLjubimac)mojLjubimac.clone();● Sada imamo 2 PasLjubimac objekta koji sadrže referencu na

isti objekat Buva● Metod clone() će kreirati novi PasLjubimac objekat

vasLjubimac i kopirati referencu na objekat Buva iz atributa buva objekta mojLjubimac u istoimeni atribut objekta vasLjubimac

Page 9: Objektno orijentisano programiranje

Komentarisanje primera

● ime ljubimca može se promeniti naredbom: vasLjubimac.setIme(”Lunja”);● Vaš pas će verovatno želeti sopstvenu buvu :) , pa možemo

promeniti ime njegove buve naredbom: vasLjubimac.getBuva().setIme(”Buvica”);● Nažalost :) , Mazina buva će se takođe preimenovati u

Buvica, pošto Maza i Lunja dele zajedničku buvu

Page 10: Objektno orijentisano programiranje

clone() , kopi-konstruktor

● Osim ako stvarno želimo da atributi dva različita objekta dele objekte na koje referišu, trebalo bi da metod clone() u našoj klasi implementiramo tako da radi kloniranje na odgovarajući način

● Kao alternativa kloniranju ( ili zajedno sa njim ) možemo našoj klasi da dodamo konstruktor koji kreira novi objekat od postojećeg

● Ako implementiramo našu sopstvenu public verziju clone() metoda da predefinišemo nasleđenu verziju, tipično ćemo kodirati ovaj metod na isti način kao što bismo i kopi-konstruktor

Page 11: Objektno orijentisano programiranje

Primer clone() metoda

● clone() metod klase PasLjubimac mogao bi biti: public Object clone() throws CloneNotSupportedException{ PasLjubimac ljubimac = new PasLjubimac(ime, rasa);

ljubimac.setIme(”Lunja”);ljubimac.getBuva().setIme(”Buvica”);

return ljubimac; }● Ovde metod kreira novi PasLjubimac objekat koristeći ime i

rasu tekućeg objekta

Page 12: Objektno orijentisano programiranje

Primer clone() metoda

● Mogli smo koristiti i nasleđeni clone() metod da dupliramo tekući objekat i onda da eksplicitno kloniramo član buva da bi referisao na nezavisan objekatpublic Object clone() throws CloneNotSupportedException{

PasLjubimac ljubimac = (PasLjubimac)super.clone(); ljubimac.buva = (Buva)buva.clone(); return ljubimac; }● Novi objekat kreiran nasleđenim clone() metodom je objekat klase

PasLjubimac, ali se vraća kao referenca klase Object● Za pristup članu buva neophodna je referenca na PasLjubimac pa je

ovde kastovanje od ključnog značaja● Efekat ove verzije clone() metoda je isti kao i prethodne verzije

Page 13: Objektno orijentisano programiranje

Metodi sa promenljivim brojem argumenata

● Moguće je pisati metod koji prima proizvoljan broj argumenata pri pozivu i argumenti koji se prosleđuju ne moraju biti istog tipa

● Da bi se razumelo kako to funkcioniše, neophodno je razumeti ulogu klase Object.

● Da metod očekuje proizvoljan broj argumenata ukazuje se navođenjem poslednjeg parametra u obliku

Object ... args● Metod može imati 0 ili više parametara pre ovoga, a ovaj

mora biti poslednji

Page 14: Objektno orijentisano programiranje

Metodi sa promenljivim brojem argumenata

● Ime parametra args predstavlja niz tipa Object[] i vrednosti argumenata su dostupne u elementima niza kao tip Object.

● Unutar tela metoda, dužina niza args nam kaže koliko argumenata je prosleđeno.

● Jednostavan primer: želimo da implementiramo statički metod koji će prihvatati proizvoljan broj argumenata i ispisivati argumente u komandnu liniju – šta god da su public static void printAll(Object ... args){ for(Object arg : args)

System.out.print(” ” + arg); System.out.println();}

● argumenti mogu biti sasvim proizvoljnih tipova● na vrednosti primitivnih tipova biće primenjen autoboxing, jer metod očekuje

reference kao argumente

Page 15: Objektno orijentisano programiranje

Metodi sa promenljivim brojem argumenata

● Jedna od upotreba mogućnosti promenljive liste argumenata u bibliotekama klasa jeste za definisanje printf() metoda u PrintStream klasi. Ovaj metod proizvodi formatirani izlaz za proizvoljnu sekvencu vrednosti proizvoljnih tipova, pri čemu je formatiranje određeno prvim argumentom metoda

● System.out je tipa PrintStream, pa se printf() može koristiti da proizvede formatirani izlaz u komandnoj liniji

Page 16: Objektno orijentisano programiranje

Ograničavanje tipova u promenljivoj listi argumenata

● Tip promenljive liste argumenata ne mora biti Object, možemo staviti proizvoljnu klasu ili interfejs.

● Argumenti onda moraju biti tog zadatog tipa ili njegovog proizvoljnog podtipa.

● Ako se stavi da je tip Object, maksimizuje se fleksibilnost jer se mogu prosleđivati argumenti proizvoljnog tipa, ali u mnogim situacijama želimo da ograničimo koji tipovi argumenata mogu da se proslede

● Primer: ako hoćemo da definišemo metod koji računa prosečnu vrednost proizvoljnog broja vrednosti koje se zadaju kao posebni argumenti, onda želimo da budemo sigurni da su argumenti isključivo numeričke vrednosti

Page 17: Objektno orijentisano programiranje

Primer

public static double average(Double ... args){ if(args.length = = 0) return 0;

double avg = 0.0; for(double value : args)

ave += value; return ave/args.length;

}● U ovom slučaju, argumenti moraju biti tipa Double ili tipa izvedenog iz Double ili –

zbog autoboxing konverzije obezbeđene kompajlerom – tipa double● Ako bismo pokušali da prosledimo vrednosti tipa int kao argumente metoda, kompajler

bi to označio kao grešku, jer ne postoji automatska konverzija tipa int u tip Double

Page 18: Objektno orijentisano programiranje

Kastovanje objekata

● Moguće je kastovati objekat u tip neke druge klase, ali jedino ako su klasa tekućeg objekta i nova klasa u istoj hijerarhiji izvedenih klasa i jedna je superklasa druge Object

Zivotinja

Macka Pas Patka

Sarplaninac

Page 19: Objektno orijentisano programiranje

Kastovanje objekata● Moguće je kastovati referencu na objekat klase naviše u tip

njene direktne ili indirektne superklase.● Npr. moguće je kastovati referencu na objekat tipa Sarplaninac

direktno u tip Pas, Zivotinja ili Object.Sarplaninac ljubimac = new Sarplaninac(”Sarko”);

Zivotinja zivotinja = (Zivotinja) ljubimac; // kastovanje Sarplaninac Zivotinja● Kada izvršimo dodelu reference na objekat promenljivoj tipa

superklase, nije neophodno eksplicitno pisati kastovanje, može se pisati i samo:Zivotinja zivotinja = ljubimac;

● Kompajler će uvek po potrebi sam ubaciti kastovanje u tip superklase

Page 20: Objektno orijentisano programiranje

Kastovanje objekata

● Kada kastujemo referencu na objekat u tip superklase, Java pamti stvarnu klasu kojoj taj objekat pripada.

● Da to nije slučaj, polimorfizam ne bi bio moguć.● Pošto se pamti informacija o originalnom tipu objekta,

moguće je i kastovanje naniže kroz hijerarhiju klasa● Ipak, kastovanje naniže se uvek mora izvršiti eksplicitno

pošto ga kompajler ne umeće sam.● Da bi kastovanje radilo, objekat mora biti legitimna instanca

klase u koju kastujemo, tj. klasa u koju kastujemo mora biti stvarna klasa objekta, ili superklasa objekta

Page 21: Objektno orijentisano programiranje

Kastovanje objekata

● Npr. moguće je kastovanje reference iz promenljive zivotinja u tip Pas ili Sarplaninac, pošto je početno objekat bio Sarplaninac, ali nije moguće kastovanje u Mačka ili Patka pošto objekat klase Sarplaninac nema klase Mačka ili Patka za superklase

● Za kastovanje zivotinja u tip Pas možemo pisati:Pas pas = (Pas) zivotinja; // kastovanje Zivotinja Pas

● Upamtiti da se promenljiva pas može koristiti samo za poziv polimorfnih metoda klase Sarplaninac koji predefinišu metode koji postoje u Pas. Ne mogu se pozivati metodi koji nisu definisani u klasi Pas. Ako želimo da zovemo metod koji postoji u klasi Sarplaninac, a ne i u klasi Pas, moramo prvo kastovati pas u tip Sarplaninac

Page 22: Objektno orijentisano programiranje

Kastovanje objekata

● Iako nije moguće kastovanje objekata koji nisu u vezi, npr. Sarplaninac Patka, moguće je postići konverziju pisanjem odgovarajućeg konstruktora, ali samo gde ima smisla raditi tako nešto

● Napiše se konstruktor u klasi u koju hoćemo da konvertujemo i on treba da prihvata objekat klase iz koje konvertujemo kao argument

● Ono što u tom slučaju radi konstruktor je prilično različito u odnosu na kastovanje. Ovde se kreira potpuno nov objekat koji je odvojen od originala, dok kastovanje predstavlja isti objekat kao različit tip

Page 23: Objektno orijentisano programiranje

Kada kastovati objekte?

● Postojaće razlozi za kastovanje objekata u oba pravca kroz hijerarhiju klasa

● npr. kadgod polimorfno izvršavamo metode, smeštamo objekte u promenljivu bazne klase i pozivamo metode izvedene klase. To u opštem slučaju uključuje kastovanje objekata izvedene klase u baznu klasu

● Drugi razlog za kastovanje naviše kroz hijerarhiju je da bi se prosledio objekat neke od mogućih potklasa metodu. Zadavanjem da je parametar baznog tipa imamo fleksibilnost da metodu prosledimo objekat proizvoljne izvedene klasenpr. ako je parametar tipa Zivotinja, možemo proslediti objekat tipa Pas, Patka ili Mačka

Page 24: Objektno orijentisano programiranje

Kada kastovati objekte?● Razlog zbog koga možda želimo da kastujemo naniže kroz

hijerarhiju klasa je da bismo izvršili metod specifičan za određenu klasu.

● Ako klasa Patka ima metod snesiJaje(), npr. ne možemo ga pozivati koristeći promenljivu tipa Zivotinja, čak i ako ona referiše na objekat klase Patka.

● Kao što je rečeno, kastovanje naniže kroz hijerarhiju klasa uvek zahteva eksplicitno kastovanje

● Primer:Patka patka = new Patka(”Pata”, ”Polarna patka”);Zivotinja ljubimac = patka; // kastovanje Patke u Zivotinjuljubimac.snesiJaje(); // Ovo se nece iskompajlirati!!!

dobićemo poruku kompajlera da metod snesiJaje() nije nađen u klasi Zivotinja

Page 25: Objektno orijentisano programiranje

Kada kastovati objekte?

● Pošto znamo da je ovaj objekat stvarno Patka, možemo izmeniti prethodni fragment koda tako da radi, tako što bi poziv metoda trebalo da bude:

((Patka)ljubimac).snesiJaje(); // ovo radi● objekat na koji pokazuje ljubimac prvo se kastuje u tip

Patka. Rezultat kastovanja se zatim koristi za poziv metoda snesiJaje(). Da objekat nije bio tipa Patka, kastovanje bi uzrokovalo izbacivanje izuzetka

Page 26: Objektno orijentisano programiranje

Preporuka

● Generalno, trebalo bi izbegavati eksplicitno kastovanje objekata koliko je to moguće, jer ono uvećava mogućnost nekorektnog kastovanja, što naše programe čini nepouzdanim.

● Ako smo pažljivo dizajnirali naše klase, eksplicitna kastovanja nam neće prečesto biti neophodna.

Page 27: Objektno orijentisano programiranje

Identifikovanje objekata

● Postoje okolnosti kada možda ne znamo tačno sa kojim tipom objekata rukujemo. To se može desiti ako se objekat izvedene klase prosledi metodu kao argument za parametar tipa bazne klase

● U nekim situacijama možda je neophodno kastovati objekat u njegov stvarni tip, recimo da bi se pozvao metod specifičan za klasu.

● Ako pokušamo da izvršimo kastovanje i ispostavi se da je to ”ilegalno”, biće izbačen izuzetak i naš program će se završiti, osim ako nismo obezbedili hvatanje izuzetaka. Jedan od načina da se to izbegne je proveriti da je objekat tipa koji očekujemo pre nego što izvršimo kastovanje

Page 28: Objektno orijentisano programiranje

Identifikovanje objekata● Ranije smo videli da možemo da koristimo metod

getClass() da bismo dobili Class objekat koji odgovara klasi i kako možemo da ga uporedimo sa instancom klase Class za klasu koju tražimo.

● To se takođe može uraditi korišćenjem operatora instanceof● Pretpostavimo da imamo promenljivu ljubimac tipa

Zivotinja i želimo da je kastujemo u tip Patka. Može ovako:Patka patka;if(ljubimac instanceof Patka) {

patka = (Patka) ljubimac;patka.snesiJaje();

}

Page 29: Objektno orijentisano programiranje

Identifikovanje objekata● Ako ljubimac ne referiše na Patka objekat, pokušaj kastovanja objekta

referisanog pomoću ljubimac u Patka doveo bi do izbacivanja izuzetka● Prethodni fragment koda može i kompaktnije da se zapiše:

if(ljubimac instanceof Patka)((Patka)ljubimac).snesiJaje();

● KOJA JE RAZLIKA IZMEĐU instanceof i getClass()?Razlika je prilično suptilna:

instanceof operator proverava da li je kastovanje objekta referisanog levim operandom u tip zadat desnim operandom dopušteno. Rezultat će biti true ako je objekat istog tipa kao desni operand ili ako je tipa proizvoljne njegove potklaseRazlika se može ilustrovati neznatnom izmenom jednog jednostavnog primera ( pretpostavka je da se u ljubimac nalazi referenca na objekat tipa Sarplaninac. Želimo da pozovemo metod definisan u klasi Pas, pa je potrebno da proverimo da ljubimac zaista referiše na Pas objekat )

Page 30: Objektno orijentisano programiranje

instanceof vs. getClass()

if(ljubimac instanceof Pas)System.out.println(”Imate psa!”);

elseSystem.out.println(”Definitivno nije pas!”);

● Dobićemo potvrdu da imamo Pas objekat čak i ako je to stvarno Sarplaninac objekat

● Ovo je dobro za potrebe kastovanja!● Međutim, ako napišemo:

if(ljubimac.getClass() = = Pas.class)System.out.println(”Imate psa!”);

elseSystem.out.println(”Definitivno nije pas!”);

izraz if će imati vrednost false jer je klasa objekta Sarplaninac, pa je njen Class objekat različit od onoga za Pas.class – morali bismo da napišemo Sarplaninac.class da bi izraz if imao vrednost true.

Page 31: Objektno orijentisano programiranje

Zaključak: instanceof ili getClass()

● Za svrhe kastovanja treba uvek koristiti operator instanceof da bi se proverio tip reference

● Kada je potrebno potvrditi tačan tip reference, treba proveriti Class objekat odgovarajući za referencu

Page 32: Objektno orijentisano programiranje

Dizajniranje klasa

● Osnovni problem u OOP jeste odlučiti na koji način treba da budu povezane klase našeg programa.

● Jedna mogućnost jeste da se kreira hijerarhija klasa njihovim izvođenjem iz bazne klase koju smo definisali i dodavanjem metoda i atributa da specijalizujemo potklase. Jedan primer ovoga su klasa Zivotinja i potklase izvedene iz nje

● Druga mogućnost je definisati skup klasa koje nisu u hijerarhiji, ali koje imaju atribute koji su sami po sebi objekti. Npr. klasa Zoo može kao atribute imati objekte klasa izvedenih iz klase Zivotinja

Page 33: Objektno orijentisano programiranje

Dizajniranje klasa● Možemo imati i hijerarhije klasa koje sadrže atribute koji su objekti –

to već imamo kod klasa izvedenih iz Zivotinja pošto one imaju atribute tipa String.

● Kod primera koje smo videli do sada, bilo je očigledno koji pristup odabrati, međutim, nije uvek tako.

● Prilično često treba izabrati između definisanja klasa kao hijerarhije i definisanja klasa sa atributima koji su objekti. Šta je najbolji pristup?

● Nema striktnog pravila. Postoje, ipak, neke smernice i neki konteksti u kojima je izbor očigledniji

● Osim želje da se odraze odnosi između tipova i objekata koji važe u stvarnosti, potreba za korišćenjem polimorfizma je primarni razlog za upotrebu potklasa ili interferjsa. To je suština OO programiranja

● Posedovanje povezanih objekata koji se mogu ekvivalentno tretirati može dosta uprostiti naše programe

Page 34: Objektno orijentisano programiranje

PRIMER

● Mnoge situacije uključuju prosuđivanje o dizajnu naših klasa.

● Razmotrimo opcije u praksi na jednostavnom primeru.● Želimo da definišemo klasu PolyLine da bismo predstavili

geometrijske entitete koji se sastoje od povezanih duži(segmenata), tj. poligonalne linije

● Deluje razumno da se tačke predstavljaju kao objekti klase Point. Tačke su dobro definisani objekti koji će se javljati u kontekstu svih vrsta geometrijskih entiteta

Page 35: Objektno orijentisano programiranje

Primer

● Sledeće pitanje koje možemo da postavimo moglo bi da bude: treba li da izvedemo klasu PolyLine iz klase Point?

● Odgovor je prilično očigledan: poligonalna linija jasno nije vrsta tačke, pa nije logično izvesti klasu PolyLine iz klase Point.

● Ovo je elementarna demonstracija ”je”-testa. Ako možemo reći da: jedna vrsta objekta ”je” specijalizovana forma druge vrste objekta, imamo dobar slučaj za izvođenje klase ( ali ne uvek – mogu postojati i kontrarazlozi ). Ako ne možemo to reći – ništa od izvođenja!

● Komplement ”je”-testa je ”ima”-test. Ako jedan objekat ”ima” komponentu koja je objekat druge klase, imamo situaciju za atribut koji je tipa klase.

Page 36: Objektno orijentisano programiranje

Primer

● Objekat House ”ima” vrata, pa bi trebalo da promenljiva tipa Door bude član klase House.

● Klasa PolyLine će sadržati nekoliko tačaka, što deluje obećavajuće, ali treba pobliže pogledati kako ćemo ih čuvati, pošto postoji nekoliko opcija.

DIZAJNIRANJE KLASE PolyLine ● Niz objekata tipa Point deluje kao dobar kandidat za atribut klase.

Međutim, postoje mane toga. Uobičajeni zahtev za poligonalne linije je mogućnost dodavanja segmenta postojećem objektu. Sa nizom za smeštanje tačaka, morali bismo da kreiramo novi niz svaki put kada dodamo segment, a zatim da kopiramo sve tačke iz starog niza u novi. To može trošiti dosta vremena ako imamo PolyLine objekat sa velikim brojem segmenata

Page 37: Objektno orijentisano programiranje

DIZAJNIRANJE KLASE PolyLine

● Imamo još jednu opciju, a to je povezana lista tačaka. U svojoj najjednostavnijoj formi, povezana lista objekata je uređenje u kome svaki objekat liste sadrži referencu na sledeći objekat kao atribut.

● Sve dok imamo promenljivu koja sadrži referencu na prvi Point objekat, možemo pristupiti svim tačkama u listi

Page 38: Objektno orijentisano programiranje

Dizajniranje klase PolyLine

● Tačke se čuvaju kao članovi ListPoint objekta.● Osim konstruktora, klasa PolyLine će trebati i metod za dodavanje

tačaka.● Možemo koristiti jedan od najmanje tri pristupa za definisanje klase

ListPoint. Mogu se navesti razlozi u korist sva 3.1. u klasi ListPoint koordinate x i y se mogu čuvati eksplicitno.

Glavni razlog protiv ovoga bio bi da već imamo enkapsulirana svojstva tačke u klasi Point, zašto to ne iskoristiti?

2. možemo posmatrati ListPoint objekat kao nešto što sadrži referencu na Point objekat, plus članove koji referišu na prethodni i naredni objekat u klasi. To nije nerazuman pristup i lako se implementira.

3. ListPoint objekat možemo posmatrati i kao specijalizovanu vrstu Point objekta, pa bismo mogli da izvedemo ListPoint klasu iz klase Point. Da li je ovo razumno ili ne zavisi od našeg gledanja na to.

Page 39: Objektno orijentisano programiranje

Dizajniranje klase PolyLine● Odlučimo se za drugu varijantu.● Klasa ListPoint se može implementirati sa atributom tipa Point, koji

definiše osnovnu tačku i njene koordinate. ListPoint objekat će imati i atribut next, tipa ListPoint kome je svrha da sadrži referencu na sledeći objekat u klasi.

● Za neki ListPoint objekat znaćemo da je poslednji element liste ako je vrednost njegovog next atributa null.

● Point.java● ListPoint.java● ListPoint objekat je sredstvo za kreiranje liste Point objekata koji

potiču od kojekuda, tako da ne moramo da brinemo oko dupliranja Point objekata smeštenih u listi. Možemo samo sačuvati referencu na Point objekat prosleđenu konstruktoru u atribut point. Atribut next treba da sadrži referencu na sledeći ListPoint u listi, i pošto on ovde nije definisan, postavljamo next na null.

Page 40: Objektno orijentisano programiranje

Dizajniranje klase PolyLine

● getNext() metod omogućuje da se odredi sledeća tačka u listi, pa je ovaj metod sredstvo pomoću kojeg se može iterirati kroz celu listu

● PolyLine.java● Klasa PolyLine ima 2 atributa start i end i oni referišu na prvu i

poslednju tačku u listi ili null ako je lista prazna● Čuvanje krajnje tačke u listi nije ključno, pošto uvek možemo da je

nađemo idući kroz listu počev od start. Međutim, posedovanje reference na krajnju tačku štedi mnogo vremena kada želimo da dodamo tačku u listu.

● Konstruktor prihvata niz Point objekata i počinje proces sklapanja objekta kreirajući listu koja sadrži jedan LinePoint objekat, kreiran od prvog elementa niza, a zatim koristi metod addPoint() da doda sve preostale tačke niza u listu.

Page 41: Objektno orijentisano programiranje

Dizajniranje klase PolyLine

● Dodavanje tačke u listu: sve što addPoint() metod radi je da kreira ListPoint objekat od Point objekta prosleđenog kao argument, postavlja atribut next stare krajnje tačke u listi da referiše na novu tačku i, konačno, smešta referencu na novu krajnju tačku u atribut end.

● TestPolyLine.java● Ova klasa radi dovoljno dobro, ali nije sasvim objektno-

orijentisana● Bolji pristup je napraviti povezanu listu opšte namene. ( Tu bi

elementi liste bili objekti klase Object. Pošto je ona superklasa svake klase, u promenljivoj tipa Object može se čuvati proizvoljna vrsta objekta )

Page 42: Objektno orijentisano programiranje

final modifajer

● final – za fiksiranje vrednosti statičkog atributa klase● Ključna reč final može se koristiti i u definiciji metoda i u

definiciji klase● Ako želimo da sprečimo da se u potklasi predefiniše metod klase,

taj metod treba deklarisati kao final u baznoj klasi.● Pokušaj da se predefiniše final metod u potklasi rezultovaće

označavanjem novog metoda kao greške od stane kompajlera.● Očigledno, apstraktni metod ne može biti deklarisan kao final jer

mora biti definisan u nekoj potklasi.● Ako deklarišemo klasu kao final, sprečićemo da proizvoljna

potklasa može da se izvede iz nje.

Page 43: Objektno orijentisano programiranje

final modifajer

public final class PolyLine{// Definicija klase kao ranije ...

}● Ako onda pokušamo da izvedemo klasu iz ove klase,

kompajler će prijaviti grešku.● Apstraktna klasa ne može biti deklarisana kao final pošto će

to sprečiti da apstraktni metodi klase budu ikada definisani.● Deklarisanje klase kao final je drastičan korak koji sprečava

da funkcionalnost klase bude proširena izvođenjem, pa treba da budemo potpuno sigurni da je to ono što želimo.

Page 44: Objektno orijentisano programiranje

Interfejsi

● U klasama koje smo izveli iz klase Zivotinja, imali smo zajednički metod zvuk(), koji je individualno implementiran u svakoj od potklasa. Potpis metoda je bio isti u svakoj klasi i metod se mogao polimorfno pozivati.

● Glavni razlog da se najpre definiše klasa Zivotinja, a zatim Pas, Macka itd. iz nje, jeste da bismo mogli da koristimo polimorfizam.

● Kada je sve što želimo skup jednog ili više metoda koje treba implementirati u različitim klasama tako da možemo da ih zovemo koristeći polimorfizam, možemo koristiti tzv. interfejs.

Page 45: Objektno orijentisano programiranje

Interfejsi● Interfejs je, u suštini, kolekcija povezanih konstanti i/ili

apstraktnih metoda i u većini slučajeva sadrži samo metode. Interfejs ne definiše šta radi metod. On samo definiše njegov oblik – ime, parametre, povratni tip, tako da su po definiciji metodi u interfejsu apstraktni.

● Da bismo koristili interfejs, implementiramo interfejs u klasi, tj. deklarišemo da klasa implementira interfejs i pišemo kod za svaki od metoda koji interfejs deklariše kao deo definicije klase.

● Kada klasa implementira interfejs, sve konstante koje su eventualno definisane u definiciji interfejsa direktno su dostupne u klasi, upravo kao da su nasleđene iz bazne klase

Page 46: Objektno orijentisano programiranje

Interfejsi

● Interfejs može sadržati konstante, apstraktne metode ili i jedne i druge

● Metodi u interfejsu su uvek public i abstract, pa ne moramo to eksplicitno da navodimo

● Smatra se lošom programerskom praksom zadavati bilo kakav atribut za njih, i definitivno se ne mogu dodati drugi atributi osim tih podrazumevanih (public, abstract). Ovo povlači da metodi deklarisani u interfejsu nikada NE MOGU biti statički

● Konstante u interfejsu su uvek public, static i final, pa ni za njih nema potrebe navoditi eksplicitno ove atribute

Page 47: Objektno orijentisano programiranje

Interfejsi

● Interfejs se deklariše kao i klasa, ali koristeći ključnu reč interface umesto class. Definiciju interfejsa čuvamo u fajlu sa ekstenzijom .java i imenom istim kao i ime interfejsa.

● Ime koje damo interfejsu mora se razlikovati od imena ostalih interfejsa i klasa istog paketa.

Page 48: Objektno orijentisano programiranje

Enkapsuliranje konstanti u programu

● Često se dešava da program koristi skup konstantnih vrednosti koje želimo da definišemo samo jednom

● U verzijama Jave pre 5.0, uobičajeni pristup bio je da se definiše skup povezanih konstanti u interfejsu, a zatim implementira interfejs u svakoj klasi koja koristi neku od tih konstanti. Taj pristup je zastareo zbog mogućnosti static import-a

● Mogućnost importovanja statičkih članova klase, uvedena u Javi 5, obezbeđuje odličan način rukovanja konstantama u programu.

● Međutim, upotreba interfejsa u te svrhe je u prošlosti bila vrlo rasprostranjena

● Upotreba static import-a za pristup konstantama definisanim u nekoj klasi je mnogo čistiji i bolji način da se skup konstanti učini dostupnim gde god je potreban.

Page 49: Objektno orijentisano programiranje

Konstante u interfejsu

public interface Konstante{double PI = 3.14;

double E = 2.72; double TRIPLE_E=3*E;

}● Pošto su konstante u interfejsu uvek static i final ( i public,

ali to u ovoj rečenici nije bitno), moramo uvek obezbediti inicijalne vrednosti za te konstante.

● Vrednost jedne konstante može se izraziti u terminima neke prethodne kao što je to slučaj sa TRIPLE_E.

● Pošto smo interfejs deklarisali kao public, konstante su dostupne i izvan paketa u kome se nalazi interfejs.

Page 50: Objektno orijentisano programiranje

Konstante u interfejsu● Možemo pristupati konstantama definisanim u interfejsima na isti način kao i statičkim

i public atributima klase – kvalifikovanjem njihovih imena imenom interfejsanpr.

public class MojaKlasa{...return r * r * Konstante.PI;...

}● Pošto interfejs Konstante uključuje samo konstante, klasa im može pristupiti koristeći

njihova nekvalifikovana imena deklarisanjem da klasa implementira ovaj interfejs. To je bila tehnika korišćena u prošlostinpr.

public MojaDrugaKlasa implements Konstante{...return r * r * PI;...

}● Konstante definisane u interfejsu Konstante su sada članovi klase MojaDrugaKlasa i

biće nasleđeni u proizvoljnoj izvedenoj klasi

Page 51: Objektno orijentisano programiranje

Konstante definisane u klasi

● Možemo definisati klasu koja će sadržati isti skup konstanti kao interfejs:package matematika;

public class Konstante{public static final double PI = 3.14;public static final double E = 2.72;public static final double TRIPLE_E = 3 * E;

}● Naravno, možemo pristupati članovima klase Konstante

izvan te klase kvalifikovanim imenom klase, npr.Konstante.TRIPLE_E

Page 52: Objektno orijentisano programiranje

Konstante definisane u klasi

● Alternativa i uobičajeniji pristup je importovanje statičkih članova klase u proizvoljnu klasu koja koristi neku od ovih konstanti. To će omogućiti korišćenje konstanti pomoću njihovih nekvalifikovanih imena. U ovom slučaju, klasa mora biti u imenovanom paketu, jer import deklaracija ne može da se primeni na bezimeni paket

● npr.import static matematika.Konstante.*;public class MojaDrugaKlasa{

...return r * r * PI;

}

Page 53: Objektno orijentisano programiranje

Interfejsi koji deklarišu metode

● Primarna svrha interfejsa je da definiše eksterni oblik skupa metoda koji predstavljaju određenu funkcionalnost

● Svaki metod deklarisan u interfejsu mora imati definiciju unutar klase koja implementira taj interfejs ako hoćemo da kreiramo konkretne objekte te klase

● Pošto su metodi u interfejsu po definiciji public, moramo koristiti ključnu reč public kada ih definišemo u našoj klasi – inače se kod neće iskompajlirati. Implementacija metoda interfejsa u klasi ne sme imati pristupni atribut koji je restriktivniji od implicitnog u deklaraciji apstraktnog metoda, a ne postoji manje restriktivan atribut od public.

Page 54: Objektno orijentisano programiranje

Interfejsi koji deklarišu metode

● Klasa može implementirati više od jednog interfejsa. U tom slučaju, pišemo imena svih interfejsa koje klasa implementira razdvojene zapetama nakon ključne reči implements. Npr.public class MojaKlasa implements Int1, Int2, Int3 {...}

● Ova klasa implementira 3 interfejsa.● Telo klase sadržaće definicije metoda deklarisanih u sva 3

interfejsa● Ne mora se implementirati svaki metod interfejsa, ali onda

postoje neke posledice toga

Page 55: Objektno orijentisano programiranje

Delimična implementacija interfejsa● Moguće je izostaviti implementaciju jednog ili većeg broja metoda

interfejsa u klasi koja implementira interfejs, ali u tom slučaju klasa nasleđuje neke apstraktne metode od interfejsa, pa moramo deklaristi samu klasu kao apstraktnu: import static matematika.Konstante.E;

import static matematika.Konstante.PI; public abstract class MojaKlasa implements Naredbe{...} i neka npr. klasa MojaKlasa implementira samo neke od metoda

interfejsa Naredbe● Ne možemo kreirati objekte (apstraktne) klase MojaKlasa● Da bismo dospeli do korisne klase, moramo definisati potklasu klase

MojaKlasa koja implementira preostale metode interfejsa.● Deklaracija klase kao abstract je obavezna kada ne implementiramo

sve metode deklarisane u interfejsu. Kompajler će se buniti ako to zaboravimo.

Page 56: Objektno orijentisano programiranje

Cloneable interfejs

● Rečeno je ranije da moramo da implementiramo interfejs Cloneable da bismo koristili nasleđeni metod clone().

● Zapravo, ovaj interfejs je prazan, bez metoda ili konstanti, pa je sve što je potrebno da bi se implementirao u klasi, navesti da ga ta klasa implementira.

● To znači da je samo potrebno napisati nešto nalik:public MojaKlasa implements Cloneable{...}

● Jedina svrha interfejsa Cloneable je da glumi fleg koji signalizira da li smo spremni da dozvolimo da objekti naše klase budu klonirani ili ne.

● Čak i ako smo definisali public clone() metod, kompajler neće dopustiti da se taj metod poziva za objekte naše klase osim ako takođe ne zadamo da naša klasa implementira Cloneable interfejs.

Page 57: Objektno orijentisano programiranje

Izvođenje iz interfejsa

● Možemo definisati jedan interfejs na osnovu drugog korišćenjem ključne reči extends za identifikovanje imena baznog interfejsa. To je istog oblika koji koristimo da izvedemo jednu klasu iz druge

● Interfejs koji se izvodi dobija sve metode i konstante od interfejsa iz koga se izvodi

public interface Konverzija extends Konstante{...}● Interfejs iz koga se vrši izvođenje naziva se i

super-interfejsom za interfejs koji se izvodi.

Page 58: Objektno orijentisano programiranje

Interfejsi i višestruko nasleđivanje

● Za razliku od klase koja može da nasledi samo jednu klasu, interfejs može da nasledi proizvoljan broj interfejsa.

● Da bismo definisali interfejs koji nasleđuje članove nekoliko drugih interfejsa, zadajemo imena tih interfejsa razdvojena zapetama nakon ključne reči extends, npr.public interface MojInterfejs extends TvojInterfejs, NasInterfejs{...}

● Sada MojInterfejs nasleđuje sve metode i konstante članove interfejsa TvojInterfejs i NasInterfejs

● To se naziva višestrukim nasleđivanjem● U Javi, klase ne podržavaju, a interfejsi podržavaju

višestruko nasleđivanje

Page 59: Objektno orijentisano programiranje

Interfejsi i višestruko nasleđivanje

● Potrebna je pažnja prilikom korišćenja ove mogućnosti. Ako 2 ili više super-interfejsa deklarišu metod sa istim potpisom, taj metod mora imati isti povratni tip u svim interfejsima koji ga deklarišu. Ako ne, kompajler će prijaviti grešku. Ovo zbog toga što bi bilo nemoguće da klasa implementira oba metoda pošto imaju isti potpis. Ako je metod deklarisan identično u svim interfejsima koji ga deklarišu, onda će jedna definicija u klasi zadovoljiti sve interfejse

● Kao što je rečeno ranije, svaki metod u klasi mora imati jednistven potpis, a povratni tip nije deo toga

Page 60: Objektno orijentisano programiranje

Korišćenje interfejsa● Za šta treba koristiti interfejse?● Interfejs koji deklariše metode definiše standardni skup

operacija. Razne klase mogu dodati takav standardni interfejs implementirajući ga. Tako objekti raznih klasa mogu da dele zajednički skup operacija. Naravno, data operacija u jednoj klasi može biti implementirana posve različito od načina na koji je implementirana u drugoj klasi. Ali, način na koji se poziva operacija je isti za objekte svih klasa koje implementiraju interfejs.

● Najvažnija upotreba interfejsa: pošto interfejs definiše tip, možemo izvršiti polimorfizam kroz skup klasa koje implementiraju isti interfejs. To je jako korisno. Pogledajmo

Page 61: Objektno orijentisano programiranje

Interfejsi i polimorfizam● Nije moguće kreirati objekte tipa interfejsa, ali moguće je

kreirati promenljivu tipa interfejsa. Npr.Konstante konst = null; // promenljiva tipa interfejsa Konstante

● Ako ne možemo kreirati objekte tipa Konstante, kakva korist od toga? Koristimo tu promenljivu za smeštanje reference na objekat proizvoljne klase koja implementira interfejs Konstante.

● To znači da ovu promenljivu možemo koristiti kako bismo polimorfno pozivali metode deklarisane u interfejsu Konstante

● Videćemo kako to izgleda na pogodnom primeru koji se odnosi na kućnu audio/video opremu i daljinsko upravljanje

Page 62: Objektno orijentisano programiranje

Pogodan primer – interfejsi i polimorfizam

● TV, hi-fi, VCR, DVD player i svaki od njih ima svoj daljinski upravljač.

● Svi daljinski upravljači verovatno imaju neki zajednički podskup dugmadi – power on/off, volume up, volume down, mute, itd.

● Želimo ”fancy” univerzalni daljinski upravljač – vrstu jedinstvene definicije daljinskog upravljača koji će odgovarati svoj opremi

● Univerzalni daljinski ima mnoštvo sličnosti sa interfejsom. Sam po sebi, univerzalni daljinski ne radi ništa. On definiše skup dugmadi za standardne operacije, ali operacija za svako dugme mora biti specifično programirana da odgovara svakoj vrsti uređaja kojim želimo da upravljamo

Page 63: Objektno orijentisano programiranje

Primer – univerzalni daljinski

● TV, VCR, DVD itd. možemo predstaviti klasama, a svaka od njih će koristiti isti interfejs daljinskog upravljanja – tj. skup dugmadi – ali svaka na drugačiji način

● RemoteControl.javapublic interface RemoteControl{...}

● U interfejsu ne postoji definicija nijednog metoda● Metodi deklarisani u interfejsu su uvek apstraktni po definiciji, a

takodje su i public. ● Sada, proizvoljna klasa koja zahteva korišćenje funkcionalnosti

obezbeđene RemoteControl interfejsom samo ima da deklariše da implementira RemoteControl interfejs i da uključi definicije za svaki od metoda iz interfejsa

Page 64: Objektno orijentisano programiranje

Primer – univerzalni daljinski● TV.java

import static java.lang.Math.max; import static java.lang.Math.min;

public class TV implements RemoteControl {...}● Ova klasa implementira sve metode deklarisane u interfejsu

RemoteControl, i svaki metod ispisuje poruku tako da znamo kada je pozvan.

● VCR.java● Klasa VCR takođe implementira RemoteControl● Naravno, možemo nastaviti i definisati klase za druge vrste

uređaja koje koriste daljinski, ali ove dve su dovoljne za demonstraciju principa

Page 65: Objektno orijentisano programiranje

Primer – univerzalni daljinski

● TestRemoteControl.javaimport static java.lang.Math.random;

public class TestRemoteControl{...}● Ovo je klasa koja operiše i TV i VCR objektima preko

promenljive tipa RemoteControl● Promenljiva remote je tipa RemoteControl pa je možemo koristiti

za smeštanje reference na objekat proizvoljne klase koja implementira RemoteControl interfejs

● Unutar for-petlje kreiramo na slučajan način TV ili VCR objekat● Pošto se tip objekta određuje u vreme izvršavanja i na slučajan

način, izlaz iz programa demonstrira polimorfizam u akciji kroz promenljivu tipa interfejsa

Page 66: Objektno orijentisano programiranje

Korišćenje više interfejsa● RemoteControl objekat u prethodnom primeru može se

koristiti za poziv samo onih metoda koji su deklarisani u interfejsu.

● Ako klasa implementira neki drugi interfejs osim RemoteControl, onda bi za poziv metoda deklarisanih u tom interfejsu trebalo ili koristiti promenljivu tipa tog interfejsa za čuvanje reference na objekat ili kastovati referencu na objekat u tip njegove stvarne klase

● Neka je klasa definisana sa:public class MojaKlasa implements RemoteControl,

AbsoluteControl{// Definicija klase koja uključuje metode iz oba interfejsa

}

Page 67: Objektno orijentisano programiranje

Korišćenje više interfejsa

● Pošto klasa implementira RemoteControl i AbsoluteControl, možemo smestiti objekat tipa MojaKlasa u promenljivu bilo kog od tipova ova 2 interfejsa, npr.AbsoluteControl ac = new MojaKlasa();

● Sada možemo koristiti promenljivu ac za pozivanje metoda deklarisanih u AbsoluteControl interfejsu. Međutim, ne možemo pozivati metode deklarisane u RemoteControl interfejsu koristeći ac, čak i ako referenca na objekat koju čuva ima ove metode.

● Jedna mogućnost je kastovati referencu u njen originalni klasni tip:((MojaKlasa)ac).powerOnOff();

Page 68: Objektno orijentisano programiranje

Korišćenje više interfejsa● Pošto kastujemo referencu u tip MojaKlasa, možemo zvati proizvoljan

metod definisan u toj klasi. Međutim, ovako ne možemo dobiti polimorfno ponašanje. Kompajler će odrediti koji metod se poziva u vreme kompajliranja

● Da bismo pozivali metode iz RemoteControl polimorfno, moraćemo da imamo referencu sačuvanu kao taj tip (RemoteControl). Znajući da je objekat tipa klase koja implementira RemoteControl interfejs, možemo od reference smeštene u ac dobiti referencu tipa RemoteControl:

if(ac instanceof RemoteControl)((RemoteControl)ac).mute();

● Čak i ako interfejsi RemoteControl i AbsoluteControl nisu ni u kakvoj vezi, možemo kastovati referencu iz ac u tip RemoteControl. To je moguće jer je objekat referisan pomoću ac zapravo tipa MojaKlasa, koji implementira oba interfejsa.

Page 69: Objektno orijentisano programiranje

Parametri metoda tipa interfejsa● Parametar metoda može biti tipa interfejsa.● To specijalno znači da se kao argument može proslediti

objekat proizvoljne klase koja implementira taj interfejs● Zadavanjem da je tip parametra interfejs, nagoveštavamo da

je metod zainteresovan samo za metode interfejsa. Sve dok je objekat tipa koji implementira te metode, on je prihvatljiv kao argument.

● Ova tehnika deklarisanja parametra interfejsnog tipa se intenzivno koristi unutar biblioteke klasa.

● Klase String, StringBuilder i StringBuffer implementiraju CharSequence interfejs, a postoji mnoštvo njihovih metoda koji imaju parametre tipa ovog interfejsa