Reutilizarea claselor

 

"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.