"The
object has three properties, which makes it a simple, yet powerful model
building block. It has state so it can model memory. It has behavior, so that
it can model dynamic processes. And it is encapsulated, so that it can hide complexity."
—Trygve Reenskaug
Sistemele software sunt similare sistemelor reale. La fel cum un sistem
real este format din părţi componente care interacţionează
între ele, la fel sistemele software sunt formate din părţi
componente care interacţionează între ele.
O aplicaţi software
orientată pe obiecte este compusă
din obiecte care interacţionează
în scopul indeplinirii unui set de
funcţionalităţi pentru care aplicaţia a fost gândită.
Fiecare obiect îndeplineşte
unul sau mai multe roluri în cadrul
aplicaţie.
In procesul de analiză al obiectelor şi al rolurilor pe care
acestea le joacă în cadrul unei aplicaţii este util să ne
raportăm la următoarele posibile roluri pe care un obiect le-ar putea
îndeplini:
-
stocare
informaţii – memorează informaţii şi oferă acces la el
-
structură
– menţine relaţii între obiecte şi oferă informaţii
despre aceste legături
-
prestator
de servicii – efectuează activiăţi
-
coordonator
– reacţionează la evenimente ce apar în cadrul aplicaţiei prin
delegarea de responsabilităţi sau de activităţi către
alte obiecte
-
interfaţă
– transformă sau transferă informaţii şi mesaje între
diferite părţi subcomponente ale systemului
Pot exista desigur şi situaţii în care un obiect să joace
mai multe roluri în acelaşi timp.
Limbajele orientate pe obiecte oferă programatorului două mecanisme
prin care poate crea colecţii de obiecte care interacţionează
în scopul îndeplinirii unui set de funcţionalităţi: compoziţia şi moştenirea.
Compozitia
Compoziţia este procesul de construire a unei clase prin
adăugarea în cadrul acesteia a unuia sau mai multor obiecte.
EXEMPLU:
class TV{
RemoteControl rc;
Display d;
ElectronicBoard eb;
booleab state
int size;
....
void turnOn(){...}
void turnOFF(){...}
}
EXEMPLU:
class Persoana{
String
nume;
Adresa adresa;
...
}
În exemplele anterioare clasele TV şi Persoana conţin
referinţe către alte obiecte şi exemplifică conceptul de
compoziţie. Ţ
Moştenirea
Moştenirea este procesul de construirea a unei clase plecând de la
o clasă existentă şi adăugând noi caracteristici, sau
modificând caracteristici existente. Clasa de la care se moştenesc
caracteristicile se mai numeşte superclasă
iar clasa care moşteneşte caracteristicile se mai numeşte
subclasă.
Se foloseşte în mod comun termenul de specializare care defineşte noţiunea de moştenirea.
O subclasă specializează o superclasă
deoarece subclasa prin adăugarea de noi roluri devine mai puţin
generală.
Pentru a specifica faptul că o clasă moşteneşte o
altă clasă se utilizează cuvântul cheie extends.
EXEMPLU:
package
isp.lab2.persoane;
public class
Persoana {
String nume;
Adresa adr;
void setAdresa(Adresa
a){adr = a}
void afiseaza(){
System.out.println("Nume="+nume);
}
}
class
Angajat extends Persoana{
int venit;
void afiseaza(){
super.afiseaza();
System.out.println("Venit="+venit);
}
int calculeazaImpozit(){
return venit/2;
}
}
class
Adresa{
String strada;
int nr;
}
Clasa Persoana modelează un concept din lumea reală, şi
anume o persoană. După cum se observă s-a decis că
această clasă să conţină două atribute. Atribut
nume este de tip String (clasa String
face parte din librăriile standard java şi este folosită pentru
manipularea de şiruri de caractere) şi permite memorarea numelui
persoanei. Atributul adr este de tip Adresa (clasa Adresa este
definită în cadrul aceluiaşi program) şi permite memorarea
adresei unei persoane. Metoda afisare()
afişează numelui persoane. în continuare s-a construit o nouă
clasă cu numele Angajat. Dar cum un angajat este o persoană dar are
in plus o serie de caracteristici suplimentare s-a decis construirea unei clase
Angajat care să moştenească caracteristicile clasei Persoana
şi care să definească acele atribute pe care le are în plus un
Angajat.
Clasa Angajat moşteneşte metodele afiseaza
şi calculeazaImpozit şi atributul nume.
Obiectele de tip angajat vor conţine aşadar şi caracteristicile
definite în cadrul clasei Persoana pe lângă cele definite în cadrul clasei
Angajat.
Există posibilitatea ca în cadrul unei subclase să
modificăm comportamentul unei metode moştenite dintr-o clasă de
bază după cum se vede în cazul funcţie afisare.
Operaţia prin care în cadrul unei clase derivate (subclase) se rescrie corpul unei funcţii dintr-o clasă de
bază (superclase) se numeşte suprascriere (eng.
overwirte).
Cuvântul cheie super este folosit în cadrul exemplului
anterior pentru a forţa apelarea unei metode din cadrul unei clase de
bază (vezi exemplul anterior).
OBSERVATIE: Aplicaţia prezentată mai sus ilustrează
folosirea în cadrul aceleiaşi aplicaţii a conceptelor de
compoziţie şi moştenire. În general în orice aplicaţie java
regăsim ambele concepte utilizate. Este important de reţinut faptul
că orice clasă java moşteneşte în mod implicit
(fără a fi nevoie de cuvântul cheie special extend)
caracteristicile clasei Object din pachetul standard java.lang.
Iniţializarea claselor de
bază şi a claselor derivate
Iniţializarea atributelor claselor de bază şi claselor
derivate trebuie realizată prin intermediul constructorilor. În continuare
este prezentată o variantă îmbunătăţită a
exemplului anterior în cadrul căreia sunt adăugaţi constructorii
pentru iniţializarea atributelor.
package
isp.lab2.persoane;
public class
Persoana {
private String nume;
private Adresa adr;
public Persoana(String n, Adresa
a){nume=n;adr=a;}
public void afiseaza(){
System.out.println("Nume="+nume);
}
public static void main(String[] args){
Adresa a = new
Adresa("stradaX",15);
Persoana p1 = new
Persoana("Alin",a);
Angajat p2 = new Angajat("Jon", new
Adresa("Strada mare",142),2000);
p1.afiseaza();
p2.afiseaza();
System.out.println("Impozit
persoana "+p2+"="+ p2.calculeazaImpozit());
}
}
class
Angajat extends Persoana{
private int venit;
Angajat(String n, Adresa a, int v){
super(n,a);
venit = v;
}
public void afiseaza(){
super.afiseaza();
System.out.println("Venit="+venit);
}
public int calculeazaImpozit(){
return venit/2;
}
}
class
Adresa{
String strada;
int nr;
Adresa(String s, int n){strada = s;nr=n;}
}
Deşi în cadrul clasei derivate nu sunt definite atributele nume
şi adr acestea trebuieiesc
inţializate întrucât sunt moştenite din
cadrul clasei Persoana. Dar, întrucât aceste două atribute sunt declarate
private în cadrul clasei de bază, în cadrul clasei derivate nu pot fi
accesate direct pentru a fi iniţializate, astfel încât se observă
că prima instrucţiune în cadrul constructorului clasei derivate este super(n,a) care asigură
apelare constructorului din clasa de bază pentru a asigura
iniţializarea celor două atribute. Se observă aşadar a
două utilitate a cuvântului cheie super.
Dacă cele două atributele ar fi fost declarate cu
specificatorul de acces public, protected sau acces
de pachet (fără nici un specificator), s-ar fi putut accesa aceste
două atribute din cadrul constructorului clasei derivate:
Angajat(String
n, Adresa a, int v){
nume = n
adr = a;
venit = v;
}
OBSERVATIE: Se recomandă ca atributele unei clase să fie
declarate private.
În momentul construirii claselor trebuie să se asigure
iniţializarea corectă atributelor acestora prin definirea
constructorilor corespunzători. În cadrul constructorilor claselor
derivate trebuie să se asigure apelarea unui dintre constructorii din
clasele de bază – în caz contrar compilatorul va atenţiona
programatorul.
EXERCITIU: Construiţi un nou proiect Java şi
adăugaţi aplicaţia de mai sus. Testaţi aplicaţia.
Adăugaţi în cadrul aplicaţiei o nouă clasă care
să modeleze un elev şi construiţi un obiect e acest tip.