APSTRAKTNE KLASE I INTERFEJSI
Prethodno
|<Nasleđivanje klasa |
Sledeće
Grafika u Javi>| |
Apstraktne klase i interfejsi iako imaju značajne razlike imaju zajedničko to što nekim klasama definišu jednu ili više metoda koje te klase treba da implementiraju.
Apstraktne klase to rade unutar hijerarhije klasa, klasama koje ih proširuju(nasleđuju), tj, njenim subklasama, dok interfejs to radi sa bilo kojom klasom sa kojom se poveže, nevezano za hijerarhiju klasa.
Te metode koje su u obavezi da se implementiraju(dovrše) u pomenutim klasama su unutar interfejsa i apstraktnih klasa "apstraktne", odnosno navedene su bez tela metode. Postoji samo naslovna linija metode, bez tela.
Ideja je da se korisniku prikaže samo šta određena metoda može da uradi, ali ne i kako radi, tj. ono šta se dešava u telu metode.
Apstraktne klase to rade unutar hijerarhije klasa, klasama koje ih proširuju(nasleđuju), tj, njenim subklasama, dok interfejs to radi sa bilo kojom klasom sa kojom se poveže, nevezano za hijerarhiju klasa.
Te metode koje su u obavezi da se implementiraju(dovrše) u pomenutim klasama su unutar interfejsa i apstraktnih klasa "apstraktne", odnosno navedene su bez tela metode. Postoji samo naslovna linija metode, bez tela.
Ideja je da se korisniku prikaže samo šta određena metoda može da uradi, ali ne i kako radi, tj. ono šta se dešava u telu metode.
Npr. kompletna metoda koja recimo računa površinu kruga bi bila:
public double povrsinaKruga(double r) {
//Povrsina
double p= r*r*Math.PI;
return p;
}double p= r*r*Math.PI;
return p;
Ovo bi zapravo bila implementirana metoda gde se vidi šta može da uradi i kako to može da uradi.
Unutar apstrakne klase apstraktna metoda bi izgledala:
Unutar apstrakne klase apstraktna metoda bi izgledala:
public abstract double povrsinaKruga(double r) ;
Vidimo da ima samo naslovnu liniju, ne i telo metode. Unutar naslovne linije mora da se doda službena reč abstract.
Dakle korisnik vidi ono što je dovoljno da zna "o metodi". Vidi naziv metode, parametre koje treba poslati metodi i tip povratne vrednosti.
Kako metoda računa površinu kruga, korisnik ne vidi, ako je metoda apstrakna.
Unutar interfejsa bi bilo:
Dakle korisnik vidi ono što je dovoljno da zna "o metodi". Vidi naziv metode, parametre koje treba poslati metodi i tip povratne vrednosti.
Kako metoda računa površinu kruga, korisnik ne vidi, ako je metoda apstrakna.
Unutar interfejsa bi bilo:
public double povrsinaKruga(double r) ;
Razlika je što kod interfejsa ne mora da se koristi reč abstract. To je zbog toga što kod apstraktnih klasa ne moraju sve metode biti apstraktne, pa da bi se razlikovale kod apstraktnih stoji i reć "abstract".
Unutar interfejsa su sve metode apstraktne, pa ne mora da stoji reč "apstract".
Vidimo da i kod jednih i kod drugih postoje određena apstrakcija.
Unutar interfejsa su sve metode apstraktne, pa ne mora da stoji reč "apstract".
Vidimo da i kod jednih i kod drugih postoje određena apstrakcija.
VIDEO LEKCIJE
Video 1: Apstraktne klase i interfejsi 1. deoVideo opisuje šta predstavljaju abstrakne klase, a šta interfejsi, njihove razlike i u nastavku je opisan primer u kome se upotrebljavaju apstrakne klase.
|
Video 2: Apstraktne klase i interfejsi 2. deoKarakteristike interfejsa. kako kreirati interfejs i povezati ga sa klasama. Primer geometrijski oblici.
|
Apstrakcija-pojam
Apstrakcija je proces skrivanja detalja implementacije i pokazivanja korisniku samo funkcionalnosti. Drugim riječima, korisniku se pokazuju samo važne stvari, a unutrašnji detalji ostaju skriveni.
Postoje dva načina za postizanje apstrakcije u javi
Postoje dva načina za postizanje apstrakcije u javi
- Apstraktna klasa (0 do 100%)
- Interfejs (100%)
Apstraktna klasa u javi(abstract class in java engl.)- karakteristike
- Klasa je deklarisana sa ključnom riječi abstract
- Ona može imati apstraktne i ne-apstraktne metode (metode sa tijelom).
- Koristi se u hijerarhiji klasa
- Ne može se instacirati(kreirati) objekat apstraktne klase.
- Ako neka klasa nasledi(proširi) apstraktnu klasu i u njoj se ne implementiraju sve apstraktne metode, onda je i ona takođe apstraktna.
- Apstraktne klase se formiraju sa ciljem da obavezno budu nasleđene, tj. da imaju svoje podklase u kojima će apstraktne metode biti implementirane.
Apstraktne klase i nasleđivanje klasa-primer:
Recimo da želimo da napravimo hijerarhiju klasa koje predstavljaju razne geometrijske površi: kvadrat, pravougaonik, paralelogram, trougao, krug, trapez. Želimo takođe u test klasi da kreiramo te objekte i izračunamo površine.
Za svaki od navedenih oblika treba napraviti klasu u koju ćemo izdvojiti osobine i metode svih objekata koji predstavljaju neku od tih geometrijskih oblika. Da bi na najbolji način kreirali hijerarhiju klasa poćićemo od klase u koju ćemo navesti ono što je zajedničko za sve geometrijske oblike. Zatim bi napravili klase za konkretne oblike koje bi nasledile ovu klasu. Nazovimo zajedničku nadklasu GeometrijskiOblik, a izvedene klase: Kvadrat, Trougao, Krug itd.
Za svaki od navedenih oblika treba napraviti klasu u koju ćemo izdvojiti osobine i metode svih objekata koji predstavljaju neku od tih geometrijskih oblika. Da bi na najbolji način kreirali hijerarhiju klasa poćićemo od klase u koju ćemo navesti ono što je zajedničko za sve geometrijske oblike. Zatim bi napravili klase za konkretne oblike koje bi nasledile ovu klasu. Nazovimo zajedničku nadklasu GeometrijskiOblik, a izvedene klase: Kvadrat, Trougao, Krug itd.
U vrhu hijerarhije klasa je apstraktna klasa GeometrijskiOblik, koja predstavlja zajedničku klasu sa sve geometrijske oblike, a nju nasleđuju klase koje predstavljaju konkretne površi: Trougao, Kvadrat i Krug.
Pogledajmo metodu koja treba da izračuna površinu konkretnog geometrijskog oblika. S obzirom da se za nadklasu GeometrijskiOblik ne zna koji je to oblik, površina još uvek ne može da se računa, tako da je ova metoda u toj klasi definisana kao apstraktna. U dijagramu klasa apstraktne metode se prikazuju sa font stilom "Italic".
Apstraktna klasa je napravljena da bi se obavezno nasledila. Objekat apstraktne klase ne može da se instancira, može smo da se deklariše i inicijalizuje na null. Npr. može se deklarisati na sledeći način:
Pogledajmo metodu koja treba da izračuna površinu konkretnog geometrijskog oblika. S obzirom da se za nadklasu GeometrijskiOblik ne zna koji je to oblik, površina još uvek ne može da se računa, tako da je ova metoda u toj klasi definisana kao apstraktna. U dijagramu klasa apstraktne metode se prikazuju sa font stilom "Italic".
Apstraktna klasa je napravljena da bi se obavezno nasledila. Objekat apstraktne klase ne može da se instancira, može smo da se deklariše i inicijalizuje na null. Npr. može se deklarisati na sledeći način:
GeometrijskiOblik oblik =null;
Mogu da se instanciraju samo objekti nasleđenih klasa npr:
Kvadrat kv=new Kvadrat();
Trougao t=new Trougao();
Krug kr=new Krug();
Trougao t=new Trougao();
Krug kr=new Krug();
Metoda povrsina() se implementira u sve sve tri podklase klase. U svim tim podklasama metoda će imati istu naslovnu liniju, ali različitu implementaciju, odnosno formula za računanje površine koja je unutar tela metode se razlikuje za svaku od konkretnih površi.
U apstraktnoj klasi mogu se naći i potpune metode, kao i u običnim klasama, kao i promenljive. Vidimo da se u apstraktnoj klasi nalaze promenljive površina P tipa double i modifikatora privatnosti protected i boja, tipa Color i modifikatora privatnosti private. Njih će naslediti ostale tri podklase.
U apstraktnoj klasi mogu se naći i potpune metode, kao i u običnim klasama, kao i promenljive. Vidimo da se u apstraktnoj klasi nalaze promenljive površina P tipa double i modifikatora privatnosti protected i boja, tipa Color i modifikatora privatnosti private. Njih će naslediti ostale tri podklase.
Apstraktne klase - sintaksa. Klasa GeometrijskiOblik
public abstract class GeometrijskiOblik {
//Povrsina
protected double P;
private Color boja;
abstract double povrsina();
public Color getBoja() {
}protected double P;
private Color boja;
abstract double povrsina();
public Color getBoja() {
return boja;
} Interfejsi-osnovni pojmovi
To je zapravo skup pravila koja svaka klasa koja ga implementira, mora poštovati. U interfejsu se nalazi spisak deklaracija metoda, dakle, samo naslovne linije metoda, bez tela. Te metode su apstrakntne. bez svoje implementacije. U interfejsu se mogu naći i konstante, ali ne i promenljivi podaci.
Primer interfejsa-sintaksa:
public interface GeometrijskiOblik {
private String PLAVA="Plava"; //Plava boja definisana kao konstanta
private String CRVENA="Crvena"; //Crvena boja definisana kao konstanta
public double calculateArea(); //an abstract method for calculating the area of some shape
public Color getBoja(); //apstraktna metoda koja daje boju
public String getNaziv(); //apstraktna metoda koja vraca naziv povrsi
}private String CRVENA="Crvena"; //Crvena boja definisana kao konstanta
public double calculateArea(); //an abstract method for calculating the area of some shape
public Color getBoja(); //apstraktna metoda koja daje boju
public String getNaziv(); //apstraktna metoda koja vraca naziv povrsi
Vidimo da se u naslovnoj liniji za razliku od klasa umesto službene reći class koristi službena reč interface prilikom definisanja interfejsa. Interfejs GeometrijskiOblik ima dve apstraktne metode povrsina() , getBoja() i getNaziv(), koje će se implementirati u onim klasama koje bi se povezale sa interfejsom GeometrijskiOblik. Takođe su definisane i konstante PLAVA i CRVENA koje predstavlju definisane boje površi.
Slično primeru koji je opisan kod apstraktnih klasa, povezaćemo ovaj interfejs sa klasama koje predstavljaju konkretne površi. Sledeći dijagram klasa prikazuje ove veze:
Slično primeru koji je opisan kod apstraktnih klasa, povezaćemo ovaj interfejs sa klasama koje predstavljaju konkretne površi. Sledeći dijagram klasa prikazuje ove veze:
U prikazanom primeru površi Kvadrat i Krug su povezane sa interfejsom GeometrijskiOblik, ne i klasa Trougao. U ovom primeru potrebno je izračunati površinu za kvadrat i krug, ne i za trougao. Kod interfejsa možemo birati za koju ćemo klasu vezati interfejs, dok bi u slučaju primera sa apstraktnim klasama morali da implementiramo metodu povrsina u svim subklasama, koje su nasledile apstraktnu klasu GeometrijskiOblik bez obzira da li mi to želimo ili ne (vidi sliku 1).
Da bi recimo, klasu Kvadrat povezali sa interfejsom u naslovnoj liniji moramo dodati službenu reč interface i naziv klase koja dati interfejs treba da implementira:
Da bi recimo, klasu Kvadrat povezali sa interfejsom u naslovnoj liniji moramo dodati službenu reč interface i naziv klase koja dati interfejs treba da implementira:
public class Kvadrat implements GeometrijskiOblik
{
}
{
Vidimo da je klasa podvucena crveno što ukazuje na grešku, jer nisu još implementirane apstraktne metode iz interfejsa. Dakle ova klasa se obavezala da će te metode implementirati(ugovor). Dodajmo sada te metode:
package geometrijskiobliciinterfejsi;
import java.util.Math;
public class Kvadrat implements GeometrijskiOblik
{
double a;
//Konstruktor sa parametrima
public Kvadrat(double a) {
//Implementirana metoda iz interfejsa GeometrijskiOblik za računanje površine
@Override
public double povrsina()
{
//Implementirana metoda iz interfejsa GeometrijskiOblik koja vraća boju
@Override
public String getColor()
{
//Implementirana metoda iz interfejsa GeometrijskiOblik koja vraća naziv
@Override
public String getNaziv()
{
}
import java.util.Math;
public class Kvadrat implements GeometrijskiOblik
{
double a;
//Konstruktor sa parametrima
public Kvadrat(double a) {
this.a = a;
}//Implementirana metoda iz interfejsa GeometrijskiOblik za računanje površine
@Override
public double povrsina()
{
double p=a*a;
return p;
}return p;
//Implementirana metoda iz interfejsa GeometrijskiOblik koja vraća boju
@Override
public String getColor()
{
return PLAVA; //Dostupna je boja jer je definisana u interfejsu koji je povezan sa ovom klasom
}//Implementirana metoda iz interfejsa GeometrijskiOblik koja vraća naziv
@Override
public String getNaziv()
{
return "Kvadrat";
}U klasi Kvadrat se moraju implementirati apstrakne metode iz interfejsa geometrijski oblik. Slično tome klasa krug takođe implementira isti interfejs, što znači da će imati iste metode, ali implementacija tih metoda neće biti ista. metoda getNaziv() vratiće "Krug", umeso "Kvadrat", metoda površina() računa površinu kruga sa odgovarajućom formulom za površinu kruga, a metoda getBoja() vratiće boju kruga, a ne kvadrata. Klasa Krug:
package geometrijskiobliciinterfejsi;
import java.util.Math;
public class Krug implements GeometrijskiOblik
{
double r;
//Konstruktor sa parametrima
public Kvadrat(double r) {
//Implementirana metoda iz interfejsa GeometrijskiOblik za računanje površine
@Override
public double povrsina()
{
//Implementirana metoda iz interfejsa GeometrijskiOblik koja vraća boju
@Override
public String getColor()
{
//Implementirana metoda iz interfejsa GeometrijskiOblik koja vraća naziv
@Override
public String getNaziv()
{
}
import java.util.Math;
public class Krug implements GeometrijskiOblik
{
double r;
//Konstruktor sa parametrima
public Kvadrat(double r) {
this.r = r;
}//Implementirana metoda iz interfejsa GeometrijskiOblik za računanje površine
@Override
public double povrsina()
{
double p=r*r*Math.PI;
return p;
}return p;
//Implementirana metoda iz interfejsa GeometrijskiOblik koja vraća boju
@Override
public String getColor()
{
return CRVENA; //Dostupna je boja jer je definisana u interfejsu koji je povezan sa ovom klasom
}//Implementirana metoda iz interfejsa GeometrijskiOblik koja vraća naziv
@Override
public String getNaziv()
{
return "Krug";
}Unutar glavne, tj. test klase kreiraćemo objekte kvadrata i kruga, zadati potrebne početne podatke, dakle, stranicu za kvadrat i poluprečnik za krug, a zatim izračunati površine i ispisati na ekranu.
Glavna test klasa:
Glavna test klasa:
package geometrijskiobliciinterfejsi;
public class GeometrijskiObliciInterfejsi
{
public class GeometrijskiObliciInterfejsi
{
Kvadrat k=new Kvadrat(10);
Trougao t=new Trougao(10, 5);
System.out.println("Povrsina: "+k.getNaziv()+" ima površinu "+
k.povrsina()+", Boja:"+k.getBoja());
System.out.println("Povrsina: "+t.getNaziv()+" ima površinu "+
t.povrsina()+", Boja:"+t.getBoja());
GeometrijskiOblik k2=new Kvadrat(45);
System.out.println("Povrsina: "+((Kvadrat)k2).getNaziv()+" ima površinu "+
k2.povrsina()+", Boja:"+k2.getBoja());
}Trougao t=new Trougao(10, 5);
System.out.println("Povrsina: "+k.getNaziv()+" ima površinu "+
k.povrsina()+", Boja:"+k.getBoja());
System.out.println("Povrsina: "+t.getNaziv()+" ima površinu "+
t.povrsina()+", Boja:"+t.getBoja());
GeometrijskiOblik k2=new Kvadrat(45);
System.out.println("Povrsina: "+((Kvadrat)k2).getNaziv()+" ima površinu "+
k2.povrsina()+", Boja:"+k2.getBoja());
Poslednji kreiran objekat je instanca klase Kvadrat jer je pozvan konstruktor klase Kvadrat, međutim, za tip podatka je stavljen interfejs GeometrijskiOblik.
Dakle, ovde vidimo da interfejs može da se koristi i kao tip podatka za objekat, u slučaju da je klasa tog objekta implementirala pomenuti interfejs.
Dakle, ovde vidimo da interfejs može da se koristi i kao tip podatka za objekat, u slučaju da je klasa tog objekta implementirala pomenuti interfejs.
Primer: Geometrijska tela
Kreirati hijerarhiju klasa geometrijskih tela : Prizma, Piramida, Lopta. U glavnoj test klasi kreirati po jedan objekat ovih tela, zadati potrebne podatke i izračunati površine i zapremine.
Posmatrajmo sledeću metodu za klase Prizma za računanje zapreminu prave četvorostrane prizme stranica osnove a i b i visine H:
Metoda se sastoji od naslovne linije i tela. U naslovnoj liniji se nalaze modifikator privatnosti(public), tip povratne vrednosti(float) naziv metode (zapremina) i parametri (u ovom primeru metoda je bez parametara). Telo metode je obuhvaćeno parom zagrada „{ }“ i u telu se nalazi implementacija metode, odnosno naredbe(naredba) koje rešavaju zadatak postavljen pred metodu, u ovom slučaju izračunavanje zapremine prizme.
Ova metoda bi najverovatnije bila pozivana iz neke druge klase preko objekta klase Prizma:
Ova metoda bi najverovatnije bila pozivana iz neke druge klase preko objekta klase Prizma:
Kada posle naziva objekta stavimo operator „.“ da bi pozvali metodu(„zapremina()“) pojavljuje se samo naziv, metode, parametri i tip povratne vrednosti, tj. ono što je definisano u „naslovnoj liniji“ metode. Treba uočiti da se telo metode odnosno sama „implementacija“ metode ovde ne vidi. Ali, implementacija metode za nekog spolja i nije „bitna“, bitno je šta ta metoda radi, kakvu vrednost vraća i koji su joj podaci potrebni. To je ono što se kod definisanja metode nalazi u naslovnoj liniji metode i predstavlja deo nekog spoljašnjeg „interfejsa“.
Interfejs bi dakle, bio skup takvih naslovnih linija metoda definisanih u nekom posebnom fajlu i sve te metode zajedno rade određen zadatak .Pošto metode u interfejsu nemaju „implementaciju“ one su apstraktne. U posmatranom primeru to bi bile metode koje definišu neki geometrijski oblik, odnosno, naziv geometrijskog oblika, površinu i zapreminu. Posmatrajmo sada dve klase koje predstavljaju prizmu i piramidu. Obe klase treba da imaju iste metode, naziv(),povrsina() i zapremina().
Interfejs bi dakle, bio skup takvih naslovnih linija metoda definisanih u nekom posebnom fajlu i sve te metode zajedno rade određen zadatak .Pošto metode u interfejsu nemaju „implementaciju“ one su apstraktne. U posmatranom primeru to bi bile metode koje definišu neki geometrijski oblik, odnosno, naziv geometrijskog oblika, površinu i zapreminu. Posmatrajmo sada dve klase koje predstavljaju prizmu i piramidu. Obe klase treba da imaju iste metode, naziv(),povrsina() i zapremina().
i druga klasa Piramida:
Vidi se da i jedna i druga klasa implementiraju iste 3 metode naziv(),povrsina() i zapremina(), dakle imaju isti spoljašnji „interfejs“, ali se razlikuje implementacija samih metoda. Ako bi skup naslovnih linija ovih metoda izdvojili u poseban fajl, kao neki koncept metoda koje svaki geometrijski oblik treba da ima možemo da te apstraktne metode napravimo kao interfejs:
Ove apstraktne metode će biti „implementirane“ u svakoj klasi koju povežemo sa tom klasom preko službene reči Java jezika „implements“. U ovom slučaju to su klase Prizma i Piramida, koje obe predstavljaju „GeometrijskiOblik“, pa obe „implementiraju“ isti interface
i
Kada se klase povežu sa interfejsom u njima se apstraktne metode iz njega obavezno moraju implementirati. To se vidi i na prethodnim slikama.
Interfejsi-primeri
U prethodno opisanom primeru, pokazana je upotreba interfejsa od početka do kraja tj. i definisanje i upotreba. U API-ju (instaliranoj javinoj biblioteci klasa) postoji veliki broj već definisanih interfejsa koje samo treba povezati sa nekom klasom. Npr. ako želimo da odreagujemo na promenu selekcije ComboBoxa, klasa u kojoj se isti nalazi treba da implementira interfejs ItemListener koji u sebi ima definisanu abstraktnu metodu ItemStateChanged();
U primeru aplikacije za iznajmljivanje filmova iz CD kluba, na formi koja prikazuje sva iznajmljivanja odabranog korisnika, nalazi se ComboBox ispunjen imenima svih korisnika u bazi
U primeru aplikacije za iznajmljivanje filmova iz CD kluba, na formi koja prikazuje sva iznajmljivanja odabranog korisnika, nalazi se ComboBox ispunjen imenima svih korisnika u bazi
Promena izabranog korisnika u ComboBox-u treba da se odrazi i na tabelu iznajmljivanja. Forma za iznajmljivanje, zato treba da implementira interfejs ItemListener odnosno njegovu abstraktnu metdu ItemStateChanged
Ovde vidimo da se ComboBox-u prosleđuje objekat čiji tip podatka u ovom slučaju nije klasa nego interface ItemListener. Da je klasa, objekat bi se napravio korišćenjem službene reči new kao što je ovde prikazano i pozivom konstruktora jawa.awt.event.ItemListener(). Pošto ItemListener nije klasa nego interfejs u kome se nalazi abstraktna neimplementirana metoda itemStateChanged, ona se ovde mora implementirati, kao što je i prikazano na slici.
Kao reakcija na klik ComboBoxa poziva se metoda promenaKorisnika(evt)
Kao reakcija na klik ComboBoxa poziva se metoda promenaKorisnika(evt)
U ovoj metodi, preko objekta evt koji nosi informacije o događaju, prvo se preuzma referenca ComboBox-a koji je proizveo događaj(izvor), a zatim se preuzme selektovana stavka u tom ComboBox-u: selObj.
Pošto se proveri da je selektovana stavka objekat tipa Korisnik, iz tog objekta se izvuče atribut koji predstavlja id korisnika koji je odabran i na osnovu njega izvuku odgovarajući podaci iz baze.
Pošto se proveri da je selektovana stavka objekat tipa Korisnik, iz tog objekta se izvuče atribut koji predstavlja id korisnika koji je odabran i na osnovu njega izvuku odgovarajući podaci iz baze.
Sledeće
Grafika u Javi>| |