Sunteți pe pagina 1din 8

11/22/13

Clase abstracte si interfete - POO

Clase abstracte si interfete


De la POO

Cuprins
1 Introducere 2 Clase abstracte 2.1 Metode abstracte 2.2 Clase abstracte in contextul mostenirii 3 Interfete 3.1 Mostenire multipla in Java 3.2 Coliziuni de nume la combinarea interfetelor 3.3 Extinderea interfetelor 3.4 Initializarea campurilor in interfete 4 Exercitii

Introducere
Fie urmatorul exemplu (Thinking in Java) care propune o ierarhie de clase pentru a descrie o suita de instrumente muzicale, cu scopul demonstrarii polimorfismului:

cursuri.cs.pub.ro/~poo/wiki/index.php/Clase_abstracte_si_interfete

1/8

11/22/13

Clase abstracte si interfete - POO

Clasa I n s t r u m e n tnu este instantiata niciodata pentru ca scopul sau este de a stabili o interfata comuna pentru toate clasele derivate. In acelasi sens, metodele clasei de baza nu vor fi apelate niciodata. Apelarea lor este ceva gresit din punct de vedere conceptual.

Clase abstracte
Dorim sa stabilim interfata comuna pentru a putea crea functionalitate diferita pentru fiecare subtip si pentru a sti ce anume au clasele derivate in comun. O clasa cu caracteristicile enumerate mai sus se numeste abstracta. Cream o clasa abstracta atunci cand dorim sa: manipulam un set de clase printr-o interfata comuna reutilizam o serie metode si membrii din aceasta clasa in clasele derivate. Metodele suprascrise in clasele derivate vor fi apelate folosind dynamic binding (http://en.wikipedia.org/wiki/Dynamic_binding_%28computer_science%29) (late binding). Acesta este un mecanism prin care compilatorul, in momentul in care nu poate determina implementarea unei metode in avans, lasa la latitudinea JVM-ului (masinii virtuale) alegerea implementarii potrivite, in functie de tipul real al obiectului. Acesta legare a implementarii de numele metodei la momentul executiei sta la baza polimorfismului. Nu exista instante ale unei clase abstracte, aceasta exprimand doar un punct de pornire pentru definirea unor instrumente reale. De aceea, crearea unui obiect al unei clase abstracte este o eroare, compilatorul Java semnaland eroare in acest caz.

Metode abstracte
Pentru a exprima faptul ca o metoda este abstracta (adica se declara doar interfata ei, nu si implementarea), Java foloseste cuvantul cheie a b s t r a c t :
a b s t r a c tv o i df ( ) ;

O clasa care contine metode abstracte este numita clasa abstracta. Daca o clasa are una sau mai multe metode abstracte atunci ea trebuie sa contina in definite cuvantul a b s t r a c t . Exemplu:
a b s t r a c tc l a s sI n s t r u m e n t{ . . . }

Deoarece o clasa abstracta este incompleta (exista metode care nu sunt definite), crearea unui obiect de tipul clasei este impiedicata de compilator.

Clase abstracte in contextul mostenirii


O clasa care mosteneste o clasa abstracta este ea insasi abstracta daca nu implementeaza toate metodele abstracte ale clasei de baza. Putem defini clase abstracte care mostenesc alte clase abstracte si tot asa. O clasa care poate fi instantiata (nu este abstracta) si care mosteneste o clasa abstracta trebuie sa implementeze (defineasca) toate metodele abstracte pe lantul mostenirii (ale tuturor claselor abstracte care ii sunt "parinti").
cursuri.cs.pub.ro/~poo/wiki/index.php/Clase_abstracte_si_interfete 2/8

11/22/13

Clase abstracte si interfete - POO

Este posibil sa declaram o clasa abstracta fara ca ea sa aiba metode abstracte . Acest lucru este folositor cand declaram o clasa pentru care nu dorim instante (nu este corect conceptual sa avem obiecte de tipul acelei clase, chiar daca definita ei este completa). Iata cum putem sa modificam exemplul instrument cu metode abstracte:

Interfete
Interfetele duc conceptul abstract un pas mai departe. Se poate considera ca o interfata este o clasa abstracta pura: permite programatorului sa stabileasca o "forma" pentru o clasa: numele metodelor, lista de argumente, valori intoarse, dar fara nicio implementare . O interfata poate contine campuri dar acestea sunt in mod implicit s t a t i csi f i n a l . Interfata este folosita pentru a descrie un protocol intre clase: o clasa care implementeaza o interfata va implementa metodele definite in interfata. Astfel orice cod care foloseste o anumita interfata stie ce metode pot fi apelate pentru acea interfata. Pentru a crea o interfata folosim cuvantul cheie i n t e r f a c ein loc de c l a s s . La fel ca in cazul claselor, interfata poate fi declarata p u b l i cdoar daca este definita intr-un fisier cu acelasi nume ca si interfata. Daca o interfata nu este declarata p u b l i catunci specifcatorul ei de acces este p a c k a g e p r i v a t e . Pentru a defini o clasa care este conforma cu o interfata anume folosim cuvantul cheie i m p l e m e n t s . Aceasta relatie este asemanatoare cu mostenirea, cu diferenta ca nu se mosteneste comportament, ci doar "interfata". Pentru a defini o interfata care mosteneste alta interfata folosim cuvantul cheie e x t e n d s . Dupa ce o interfata a fost implementata, acea implementare devine o clasa obisnuita care poate fi extinsa prin mostenire.
cursuri.cs.pub.ro/~poo/wiki/index.php/Clase_abstracte_si_interfete 3/8

11/22/13

Clase abstracte si interfete - POO

Iata exemplul dat mai sus, modificat pentru a folosi interfete:

Codul arata astfel:


i n t e r f a c eI n s t r u m e n t{ / /C o m p i l e t i m ec o n s t a n t : i n ti=5 ;/ /s t a t i c&f i n a l / /C a n n o th a v em e t h o dd e f i n i t i o n s : v o i dp l a y ( ) ;/ /A u t o m a t i c a l l yp u b l i c S t r i n gw h a t ( ) ; v o i da d j u s t ( ) ; } c l a s sS u f l a ti m p l e m e n t sI n s t r u m e n t{ p u b l i cv o i dp l a y ( ){ S y s t e m . o u t . p r i n t l n ( " S u f l a t . p l a y ( ) " ) ; } p u b l i cS t r i n gw h a t ( ){ r e t u r n" S u f l a t " ; } p u b l i cv o i da d j u s t ( ){ } } c l a s sT r o m p e t ae x t e n d sS u f l a t{ p u b l i cv o i dp l a y ( ){ S y s t e m . o u t . p r i n t l n ( " T r o m p e t a . p l a y ( ) " ) ; }
cursuri.cs.pub.ro/~poo/wiki/index.php/Clase_abstracte_si_interfete 4/8

11/22/13

Clase abstracte si interfete - POO

p u b l i cv o i da d j u s t ( ){ S y s t e m . o u t . p r i n t l n ( " T r o m p e t a . a d j u s t ( ) " ) ; } }

Implicit, specificatorul de acces pentru membrii unei interfete este p u b l i c . Atunci cand implementam o interfata trebuie sa specificam ca functiile sunt p u b l i cchiar daca in interfata ele nu au fost specificate explicit astfel. Acest lucru este necesar deoarece specificatorul de acces implicit in clase este p a c k a g e p r i v a t e , care este mai restrictiv decat p u b l i c .

Mostenire multipla in Java


Interfata nu este doar o forma "pura" a unei clase abstracte, ci are un scop mult mai inalt. Deoarece o interfata nu specifica nici un fel de implementare (nu exista nici un fel de spatiu de stocare pentru o interfata) este normal sa "combinam" mai multe interfete. Acest lucru este folositor atunci cand dorim sa afirmam ca "X este un A, un B si un C". Acest deziderat este mostenirea multipla si, datorita faptului ca o singura entitate (A, B sau C) are implementare, nu apar problemele mostenirii multiple din C++.

i n t e r f a c eC a n F i g h t{ v o i df i g h t ( ) ; } i n t e r f a c eC a n S w i m{ v o i ds w i m ( ) ; } i n t e r f a c eC a n F l y{ v o i df l y ( ) ; } c l a s sA c t i o n C h a r a c t e r{ p u b l i cv o i df i g h t ( ){ } } c l a s sH e r oe x t e n d sA c t i o n C h a r a c t e ri m p l e m e n t sC a n F i g h t ,C a n S w i m ,C a n F l y{ p u b l i cv o i ds w i m ( ){ } p u b l i cv o i df l y ( ){ } } p u b l i cc l a s sA d v e n t u r e{ s t a t i cv o i dt ( C a n F i g h tx ){ x . f i g h t ( ) ; }
cursuri.cs.pub.ro/~poo/wiki/index.php/Clase_abstracte_si_interfete 5/8

11/22/13

Clase abstracte si interfete - POO

s t a t i cv o i du ( C a n S w i mx ){ x . s w i m ( ) ; } s t a t i cv o i dv ( C a n F l yx ){ x . f l y ( ) ; } s t a t i cv o i dw ( A c t i o n C h a r a c t e rx ){ x . f i g h t ( ) ; } p u b l i cs t a t i cv o i dm a i n ( S t r i n g [ ]a r g s ){ H e r oh=n e wH e r o ( ) ; t ( h ) ;/ /T r e a ti ta saC a n F i g h t u ( h ) ;/ /T r e a ti ta saC a n S w i m v ( h ) ;/ /T r e a ti ta saC a n F l y w ( h ) ;/ /T r e a ti ta sa nA c t i o n C h a r a c t e r } }

Se observa ca H e r ocombina clasa A c t i o n C h a r a c t e rcu interfetele C a n S w i metc. Acest lucru se realizeaza specificand prima data clasa concreta (sau abstracta) (e x t e n d s ) si abia apoi i m p l e m e n t s . Metodele clasei A d v e n t u r eau drept parametri interfetele C a n S w i netc. si clasa A c t i o n C h a r a c t e r . La fiecare apel de metoda din A d v e n t u r ese face upcast de la obiectul H e r ola clasa sau interfata dorita de metoda respectiva.

Coliziuni de nume la combinarea interfetelor


Combinarea unor interfete care contin o metoda cu acelasi nume este posibila doar daca metodele nu au tipuri intoarse diferite si aceeasi lista de argumente. Totusi este preferabil ca in interfete diferite care trebuie combinate sa nu existe metode cu acelasi nume deoarece acest lucru poate duce la confuzii evidente (sunt amestecate in acest mod 3 concepte: overloading, overriding si implementation).

Extinderea interfetelor
Se pot adauga cu usurinta metode noi unei interfete prin extinderea ei intr-o alta interfata: Exemplu:
i n t e r f a c eM o n s t e r{ v o i dm e n a c e ( ) ; } i n t e r f a c eD a n g e r o u s M o n s t e re x t e n d sM o n s t e r{ v o i dd e s t r o y ( ) ; }

Deoarece campurile unei interfete sunt automat s t a t i csi f i n a l , interfetele sunt un mod convenabil de a crea
cursuri.cs.pub.ro/~poo/wiki/index.php/Clase_abstracte_si_interfete 6/8

11/22/13

Clase abstracte si interfete - POO

grupuri de constante, asemanatoare cu enum-urile din C , C++.

Initializarea campurilor in interfete


In interfete nu pot exista blank finals (campuri f i n a lneinitializate) insa pot fi initializate cu valori neconstante . Campurile fiind statice, ele vor fi initializate prima oara cand clasa este initializata.

Exercitii
1. (2p) Implementati interfata T a s kin cele 3 moduri de mai jos. La crearea claselor in Eclipse, utilizati interfata vizuala pentru precizarea interfetelor ce se doresc implementate (metodele corespunzatoare vor fi adaugate automat). Un task care sa afiseze un mesaj la output. Mesajul este specificat in constructor. Un task care genereaza un numar aleator si afiseaza un mesaj cu numarul generat la output. Generarea se face in constructor Un task care incrementeaza un contor global si afiseaza valoarea contorului dupa fiecare incremenetare. Nota: Acesta este un exemplu simplu pentru Command Pattern (http://en.wikipedia.org/wiki/Command_pattern) . 2. (3p) Interfata C o n t a i n e rspecifica interfata comuna pentru colectii de obiecte T a s k , in care se pot adauga si din care se pot elimina elemente. Creati doua tipuri de containere care implementeaza aceasta clasa: 1. (1.5p) S t a c k- care implementeaza o strategie de tip LIFO (http://en.wikipedia.org/wiki/LIFO_(computing)) 2. (1.5p) Q u e u e- care implementeaza o strategie de tip FIFO (http://en.wikipedia.org/wiki/FIFO) Evitati codul similar in locuri diferite! Hint: Puteti retine intern colectia de obiecte, utilizand clasa A r r a y L i s t
( h t t p : / / d o w n l o a d . o r a c l e . c o m / j a v a s e / 6 / d o c s / a p i / j a v a / u t i l / A r r a y L i s t . h t m l ) din biblioteca Java, ce va fi folosita asemanator clasei M y A r r a y L i s tdin Laboratorul 2. Iata un

exemplu de initializare pentru siruri:


A r r a y L i s t < S t r i n g >l i s t=n e wA r r a y L i s t < S t r i n g > ( ) ;

3. (1p) Implementati interfata I F a c t o r ycare contine o metoda ce primeste ca parametru o strategie S t r a t e g ysi care intoarce un container asociat acelei strategii. Din acest punct inainte, in programul vostru veti crea containere folosind doar aceasta clasa (nu puteti crea direct obiecte de tip S t a c ksau Q u e u e ). Evitati instantierea clasei F a c t o r yimplementate de voi la fiecare creare a unui container! Nota: Acest mod de a crea obiecte de tip C o n t a i n e relimina problema care apare in momentul in care decidem sa folosim o implementare diferita pentru un anumit tip de strategie si nu vrem sa facem modificari si in restul programului. De asemenea o astfel de abordare este utila cand avem implementari care urmaresc scopuri diferite (putem avea un F a c t o r ycare sa creeze containere optimizate pentru viteza sau un Factory cu containere ce folosesc minimum de memorie). Sablonul acesta de programare poarta denumirea de Factory Method Pattern (http://en.wikipedia.org/wiki/Factory_method_pattern) .
cursuri.cs.pub.ro/~poo/wiki/index.php/Clase_abstracte_si_interfete 7/8

11/22/13

Clase abstracte si interfete - POO

4. (3p) Creati clasa A b s t r a c t T a s k R u n n e rcare executa Task-uri, ce va contine: Un constructor ce primeste ca parametru o strategie prin care se specifica in ce ordine se vor executa task-urile (LIFO sau FIFO) O metoda a d d T a s k , care adauga un task in colectia de task-uri de executat O metoda e x e c u t e A l l , care executa toate task-urile din colectia de task-uri Dupa executia fiecarui task va avea loc o actiune - actiune abstracta, specifica claselor care mostenesc A b s t r a c t T a s k R u n n e r(vezi ex. urmator). Metoda abstracta care specifica aceasta actiune trebuie sa fie vizibila doar pentru clasele din lantul de mostenire ce porneste din A b s t r a c t T a s k R u n n e r . 5. (4p) Extindeti clasa A b s t r a c t T a s k R u n n e rin 3 moduri: (1p) P r i n t T a s k R u n n e r- care afiseaza un mesaj dupa executia unui task in care se specifica ora la care s-a executat task-ul (vezi clasa D a t e ( h t t p : / / d o w n l o a d . o r a c l e . c o m / j a v a s e / 1 . 5 . 0 / d o c s / a p i / j a v a / u t i l / D a t e . h t m l )) (1p) C o u n t T a s k R u n n e r- incrementeaza un contor local care tine minte cate task-uri s-au executat. (1p) R e d o T a s k R u n n e r- salveaza fiecare task executat intr-un container in ordinea inversa a executiei si are o metoda prin care se permite reexecutarea task-urilor. (1p) Extindeti P r i n t T a s k R u n n e rastfel incat sa se introduca o intarziere intre executiile taskurilor. Intarzierea este specificata in constructor. Pentru introducerea unei intarzieri in executia programului puteti utiliza secventa de mai jos:
t r y{ T h r e a d . s l e e p ( 1 0 0 0 ) ;/ /m i l i s e c u n d e }c a t c h( I n t e r r u p t e d E x c e p t i o ne ){ e . p r i n t S t a c k T r a c e ( ) ; }

Solutii Adus de la "http://cursuri.cs.pub.ro/~poo/wiki/index.php/Clase_abstracte_si_interfete" Ultima modificare 11:49, 1 octombrie 2011. Coninutul este disponibil sub GNU Free Documentation License 1.2.

cursuri.cs.pub.ro/~poo/wiki/index.php/Clase_abstracte_si_interfete

8/8