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.

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;
}
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:
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:
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.

VIDEO LEKCIJE

Video 1: Apstraktne klase i interfejsi 1. deo


Video 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. deo


​Karakteristike 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
  1. Apstraktna klasa (0 do 100%)
  2. Interfejs (100%)

Apstraktna klasa u javi(abstract class in java engl.)- karakteristike

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. Apstrakne klase. Primer Geometrijski oblici-dijagram klasa
Slika 1: Apstrakne klase. Primer Geometrijski oblici-dijagram klasa
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:
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();
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. 

​Apstraktne klase - sintaksa. Klasa GeometrijskiOblik

public abstract class GeometrijskiOblik {
//Povrsina
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
}
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:Interfejsi(Interface engl.). Primer Geometrijski oblici-dijagram klasa
Slika 2: Interfejsi(Interface engl.). Primer Geometrijski oblici-dijagram klasa
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:
public classKvadrat 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) {
this.a = a;
}
//Implementirana metoda iz interfejsa GeometrijskiOblik za računanje površine
@Override
public double povrsina()
{
double p=a*a;
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) {
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;
}
//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:
package 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());
}
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.

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: Interfejsi-Prepravljena metoda
Slika 1: Interfejsi-Prepravljena metoda "Zapremina()"
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:Interfejsi- Atributi objekta klase Prizma
Slika 2: Interfejsi- Atributi 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(). Interfejsi-Implementacija u klasi Prizma
Slika 3: Interfejsi-Implementacija u klasi Prizma
i druga klasa Piramida:
Implementacija u klasi Piramida
Slika 4: Implementacija u klasi 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: Interfejsi-Interfejs GeometrijskiOblik
Slika 4: Interfejsi-Interfejs GeometrijskiOblik
​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 Klasa Prizma implementira interfejs GeometrijskiOblik
Slika 7: Interfejsi-Klasa Prizma implementira interfejs GeometrijskiOblik
iSlika 7: Interfejsi-Klasa Piramida implementira interfejs GeometrijskiOblik
Slika 7: Interfejsi-Klasa Piramida implementira interfejs GeometrijskiOblik
​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 baziIznajmljivanje filmova. Primer aplikacije sa upotrebom interfejsa
Slika 8: Iznajmljivanje filmova. Primer aplikacije sa upotrebom interfejsa
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
​ItemStateChange metoda implementirana u nekoj klasi
Slika 9: ItemStateChange metoda implementirana u nekoj klasi
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)Upotreba interfejsa-metoda PromenaKorisnika
Slika 10: Upotreba interfejsa-metoda PromenaKorisnika
​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.

​​​​Prethodno
​|<Nasleđivanje klasa
​Sledeće
​​Grafika u Javi>|

Srodni članci

Klase i objekti
Grananje u programu
Prosti brojevi i faktorizacija
Matrice primeri
Trendovi u programiranju