Podsjetimo se kako funkcionira standardno,
proceduralno programiranje, na
primjer u programskom jeziku C. Program započinje izvršavanjem
funkcije main koja izvršava
postavljeni zadatak pozivanjem drugih funkcija. Program završava kad se
izvrše sve instrukcije funkcije main.
Osnovni građevni blok programa je, dakle, funkcija. Postavljeni zadatak
rješava se tako da se razbije na niz manjih zadaća od kojih se
svaka može implementirati u jednoj funkciji. Cijeli program je niz
funkcijskih poziva. U takvom stilu programiranja (proceduralno
orijentirano programiranje) prvorazrednu ulogu imaju algoritmi, koji su
implementirani u funkcijama, dok je značenje podataka drugorazredno.
U objektno orijentiranom programiranju osnovnu ulogu imaju objekti koji sadrže i podatke i funkcije (= metode). Program se konstruira kao skup objekata koji međusobno komuniciraju. Podaci koje objekt sadrži predstavljaju njegovo stanje, dok pomoću metoda on to stanje može mijenjati i komunicirati s drugim objektima.
Dakle, u osnovi svega je objekt koji:
Stoga je sav izvorni kod podijeljen u klase koje se nalaze u istoj ili različitim izvornim datotekama (s ekstenzijom .java).
Vrlo su jednostavni i objašnjeni na primjeru niže:
Klasa geometrijska figura može apstrahirati sve geometrijske figure u ravnini (kružnice, kvadrate, pravokutnike, dužine, ...). Recimo klasa Figura može biti modelirana ovako:
1 class Figura {
2 // podatak
3 int boja_Figure;
4
5 // metode
6 void nacrtaj() {
7 // implementacija
8 }
9
10 void nacrtaj(int boja) {
11 // implementacija
12 }
13
14 String ime_figure(){
15 // implemetnacija
16 }
17 }
Komentari:
Figura "čuva" jedan cjelobrojni podatak:
int boja_Figure; i tri metode. Figura ima dvije
metode istog imena, ali s
različitim brojem formalnih parametara -- to je tzv. preopterećenje
(tvz. overloading). Java pri
identifikaciji funkcije koristi ne samo njeno ime, već i broj i tip
parametara; nije moguće imati dvije metode istog imena, ali
različitih povratnih vrijednosti -razlog je jednostavan: to nema smisla;
povratna vrijednost za metode istog imena mora biti ista, ali se može
dobivati na više načina, ovisno o tome kakve ulazne podatke (formalni
parametri) imamo. Figura nema main metodu pa stoga ne predstavlja
potpuni program. Svaki program u Javi, isto kao i u jeziku C, započinje izvršavanjem
main metode. Stoga jedna od klasa u programu (i samo jedna) mora i
mati main
metodu. Ta metoda mora biti deklarirana public i static,
što će biti kasnije objašnjeno.
Figura moramo konstruirati novu klasu koja će imati
main metodu u kojoj ćemo takav objekt instancirati.
Kreiranje objekata dane klase zovemo instanciranjem objekata, a same objekte
zovemo instancama
dane klase: za instanciranje koristimo operator new.
1 class KorisnikFigure{
2
3 public static void main(String args[]) {
4
5 // fig je objekt koji reprezentira klasu Figura.
6 //
7
8 Figura fig=new Figura();
9
10 KorisnikFigure kf = new KorisnikFigure();
11 kf.ucini_nesto(fig);
12 }
13
14 void ucini_nesto(Figura x) {
15 x.nacrtaj();
16 }
17 }
KorisnikFigure ima deklarirane dvije metode, od kojih je jedna main.
Kada kompiliramo program koji sadrži klasu KorisnikFigure
i pokrenemo ga, počet će se izvršavati njegova
main metoda. U njoj se u liniji 8 instancira novi objekt tipa
Figura. Varijabla fig (tipa Figura) je
referenca na taj objekt. Štoviše, u liniji 10 se instancira objekt klase
KorisnikFigure (što se može činiti bizarno) i nakon toga se na
tom objektu (varijabla kf) poziva njegova metoda
ucini_nesto, kojoj se kao argument daje objekt fig.
ucini_nesto
u klasi KorisnikFigure, ili metodu nacrtaj klase
Figura, moramo prvo instancirati objekt te klase i zatim
metodu pozvati na objektnoj varijabli pomoću dot-operatora: na primjer,
kf.ucini_nesto(fig);
static) su posebne po tome
što ne trebaju instancirani objekt da bi bile pozvane. Zato main
mora biti static -- na početku izvršavanja programa
nema instanciranog objekta.Figure, te da definira neke nove.
1 class Kvadrat extends Figura{
2
3 //nasljedjuje sve iz Figure i dodaje novu varijablu i metodu
4
5 int duljina_stranice;
6
7 int povrsina(){
8 return duljina_stranice*duljina_stranice;
9 }
10
11 //klasa Kvadrat preradjuje metodu nacrtaj
12
13 void nacrtaj(){ //neka nova implementacija
14 }
15 }
Kvadrat
konstruira proširenjem klase Figura. U osnovi to znači da klasa
Kvadrat nasljeđuje sve podatke i metode iz klase Figura,
te deklarira samo nove varijable i metode (uz neka ograničenja koja će kasnije biti objašnjena).
U toj situaciji govorimo da klasa Kvadrat proširuje klasu Figura i
da je Figura nadklasa Kvadrata
(Kvadrat je
podklasa Figure). nacrtaj. U tom slučaju kažemo da je metoda
prerađena, tj. podklasa daje novu implementaciju metode iz nadklase.Kvadrat kv=new Kvadrat(); kv.nacrtaj(); //taj nacrtaj() je preradjen u klasi kvadrat kv.nacrtaj(3); //ovaj nacrtaj(int) je iz klase klase Figura
Krug malo niže).
Medjutim, dana klasa može
proširivati samo jednu nadklasu. C++ ima mogućnost višestrukog
naslijeđivanja, ali u praksi se najčešće koristi kroz mehanizam
višestrukog nasljeđivanja sučelja (eng. interface). Analogon toga u
Javi je mogućnost klase da implementira više sučelja. Sučelja u Javi
ćemo jako puno koristiti na isti način na koji se ona koriste i u
C++-u.
1 class Krug extends Figura{
2 //vraća ime nase figure
3 String ime_figure(){
4 return "Krug";
5 }
6 }
Kvadrat konstruirali proširenjem klase
Figura (uočite da se proširenjem klasu specijalizira).
Prirodno je stoga da svaka metoda koja kao argument očekuje objekt tipa Figura,
prihvati objekt tipa Kvadrat (ili Krug). To se naziva
polimorfizam -- jedan objekt promatramo na različitim razinama apstrakcije.KorisnikFigure korisnik = new KorisnikFigure(); Kvadrat kv = new Kvadrat(); //pozovimo metodu ucini_nesto korisnik.ucini_nesto(kv); //pozvali smo metodu na objektu prosirene klase
ucini_nesto uzima parametar tipa Figura
a pozvana je s parametrom tipa Kvadrat. To je
dozvoljeno stoga što je Kvadrat podklasa klase Figura
i prevodilac će izvršiti implicitnu konverziju reference. Izvedbena
okolina, s druge strane, pamti da je stvarni tip reference predane
metodi ucini_nesto. Na osnovu toga metoda ucini_nesto
ne poziva metod nacrtaj() iz klase Figura već prerađenu metodu
iz klase Kvadrata.
Na taj način pišemo kod koji je neovisan o tome kakvu konkretno figuru
želimo crtati; za sada imamo samo Kvadrat, Kruznicu, a kasnije možemo
dodati kakve hoćemo figure i preraditi metodu nacrtaj() kako
hoćemo, ali uvijek će se pozivati prava implementacija metode nacrtaj().
Dakle, kod metode ucini_nesto ne ovisi o konkretnoj prirodi
figure. Ovo je sama srž OOP programiranja!
kv je referenca na objekt. Reference ćemo
detaljnije objasniti na sljedećim predavanjima; istaknimo samo da su reference po svojim
svojstvima slične pokazivačima u jezicima C/C++. Uočite da se objekti
instanciraju s operatorom new
koji je analogon funkcije malloc
iz C-a. Program se sastoji od četiri izvorne datoteke KorisnikFigure.java Figura.java, Kvadrat.java, te Krug.java.
Program se prevodi naredbom
javac KorisnikFigure.java
a izvršava naredbom
java KorisnikFigure
Proučite što program radi te koje principe OOP-a možemo na njemu prepoznati. Korisno je komparirati jezike. Za one koje zanima isti program ali u C++-u i upute kako se prevodi nalaze se ovdje ovdje. C++ je jezik temeljen na C-u i sintaksa će vam biti vrlo bliska.
Sve klase (i sistemske i naše) u Javi su direktno ili indirektno izvedene iz ove
klase. Štoviše, ako se eksplicitno ne specificira nadklasa dane klase,
onda je ona uvijek java.lang.Object. Npr. HelloWorld zapravo se
prevodi kao:
1 class HelloWorld extends Object{
2
3 public static void main(String[] args){
4
5 System.out.println("Hello, World");
6
7 }
8 }
Mi ćemo često prerađivati metodu
String toString()
klase Object koja vraća reprezentaciju našeg objekta u obliku
stringa. Proučite iz Java API što je defaultna implementacija ove
metode. (Vidite niže kako naći dokumentaciju.)
Kasnije u radu sa dretvama (eng. threads) upoznat ćemo i neke druge metode te klase.
1. Ako ste dokumentaciju instalirali u C:\docs, ona u web pregledniku otvorite file:///C:/docs/api/index.html da vidite dokumentaciju o svim klasama i paketima koje čine Java API. Ovo ćete jako puno koristiti u ovom kolegiju. Ista dokumentacija se on-line može vidjeti na http://java.sun.com/j2se/1.3/docs/api/.
2. Glavna stranica dokumentacije je file:///C:/docs/index.html i ako se spustite niže do linka Java 2 Platform API Specification (NO FRAMES) doći ćete isto na file:///C:/docs/api/index.html.
3. Pretpostavimo da ste Java SDK instalirali u C:\java. Onda se u tom direktoriju nalazi datoteka src.zip. Otpakirajte je. Ona sadrži izvorni kod za Java API. Često je interesantno vidjeti kako su neke sistemske klase implementirane. Java spada u otvoreno računarstvo!
4. Precizne specifikacije jezika mogu se besplatno čitati ili skinuti sa inteneta u HTML ili PDF formatu http://java.sun.com/docs/books/jls/index.html.
Mnoštvo besplatnih knjiga u Javi može se naći http://java.sun.com/docs/index.html.