Catedra de Telecomunicatii                      

 

  24/11/2007                                       

                                     Inginerie Software (ISw)     

 

 

Laborator 2

Metode si constructori. Supraincarcarea numelor. Asocierea. Extinderea prin mostenire. Rescrierea codului (overriding).

2.1. Descrierea laboratorului

 

In aceasta lucrare de laborator vor fi acoperite urmatoarele probleme:

- Specificarea comportamentului (metodele si constructorii):

- Semnaturile metodelor si returnarea valorilor, Constructorii

            - Supraincarcarea numelor metodelor si constructorilor – polimorfismul static

- Relatii intre clase: Asocierea si utilizarea

- Studiu de caz: Clasele Mesaj si Pachet

- Clasele Grupa, DatePersonale si SituatieCurs si clasa Student actualizata

- Programare orientata spre obiecte avansata:       

- Generalizarea si specializarea claselor. 

- Mostenirea. Rescrierea codului (overriding)

- Clasele Persoana, Student, Profesor, DatePersonale, SituatieCurs si StudentMaster

- Anexe. Mediile de dezvoltare (IDE-urile) JCreator si NetBeans IDE BlueJ Edition

- Teme de casa

 

 

2.2. Metode si constructori. Supraincarcarea numelor

2.2.1. Semnatura metodei. Returnarea valorilor

 

 

Dupa invocare (apelare) metodele (functiile membru) obiectelor efectueaza sarcini (in general utilizand argumentele pasate in momentul apelului si valorile campurilor obiectului) care se pot finaliza (sau nu) inclusiv prin returnarea unei valori.

 

Definitia unei metode contine 2 parti: semnatura (antetul, declaratia) si corpul (blocul, segmentul, secventa de instructiuni a implementarii).

Semnatura specifica:

- numele metodei,

- lista de parametri formali (numarul, ordinea, tipul si numele lor),

- tipul valorii returnate,

- specificatori ai unor proprietati explicite (modificatori ai proprietatilor implicite).

 

Tipul valorii returnate poate fi unul dintre cele 8 tipuri primitive (byte, short, int, long, float, double, boolean si char), sau unul dintre cele 3 tipuri referinta (tablouri, clase si interfete Java) sau void daca metoda nu returneaza nici o valoare. Corpul metodei contine secventa de instructiuni care specifica pasii necesari indeplinirii sarcinilor (evaluari de expresii, atribuiri, decizii, iteratii, apeluri de metode, etc.). Returnarea valorilor este specificata prin instructiunea return urmata de o expresie care poate fi evaluata la o valoare de tipul declarat in semnatura.

 

In laborator: Pentru exemplul de mai jos:

1. Identificati numele metodelor.

2. Incercati sa determinati metodele definite de programator si metodele bibliotecilor Java.

3. Identificati metodele care sunt implementate (semnatura si corp) si metodele care sunt apelate.

4. Identificati numele si tipul parametrilor si valorile argumentelor in fiecare caz.

5. Identificati tipul valorilor returnate in fiecare caz.

6. Identificati instructiunile return si comparati tipul expresiilor cu tipul declarat.

 

 import javax.swing.JOptionPane;            // clasa de biblioteca (package) Java, externa
                                            // dar accesibila codului care urmeaza
 public class DialogUtilizator01 {          // clasa definita de utilizator (declaratia)
                                            // corpul clasei:
    public String nextLine(String text) {                // metode Java (operatii) 
        return JOptionPane.showInputDialog(text);        // returneaza o valoare tip String
    } 
    public int nextInt(String text) {                    // returneaza o valoare tip int
        return Integer.parseInt(JOptionPane.showInputDialog(text));   
    } 
    public void println(String text) {                 // nu returneaza nici o valoare
        JOptionPane.showMessageDialog(null, text);
    } 
 } 

 

 

In documentatia (API-ul) claselor Java pot fi gasite detalii privind clasa JOptionPane.

 

In laborator:

1. Lansati mediul BlueJ.   Inchideti proiectele anterioare (cu Ctrl+W sau Project si Close).

2. Creati un nou proiect numit dialog (cu Project, apoi New Project…, selectati D:/,

         apoi POO2007, apoi numarul grupei, apoi scrieti dialog).

3. Creati o noua clasa, numita DialogUtilizator01, cu New Class…

4. Double-click pe noua clasa (deschideti editorul) si inlocuiti codul cu cel de sus.

5. Compilati codul apoi creati un obiect din noua clasa.

 

Nu uitati: Daca bara de stare a executiei este activa () verificati cu Alt+Tab daca a aparut o fereastra Java (in spatele ferestrelor vizibile).

 

In laborator:

1. Executati metoda nextLine() dandu-i ca parametru “Introduceti numele dumneavoastra”.

    

 

2. Inspectati valoarea returnata.

                           

 

3. Executati si metodele nextInt() si println() si urmariti efectul lor.

 

 

 

Clasa Java pentru testarea clasei anterior definite:

 

 public class RunDialogUtilizator01 {   
    public static void main(String[] args) { 
        DialogUtilizator01 d01 = new DialogUtilizator01();                // obiect testat
        String linie = d01.nextLine("Introduceti numele dumneavoastra");  // metoda testata
        d01.println("Buna ziua " + linie + ".  Bine ai venit in lumea Java!"); 
    } 
 }

 

 

In laborator:

1. Tot in proiectul dialog, creati o noua clasa numita RunDialogUtilizator01 

2. Double-click pe noua clasa (deschideti editorul) si inlocuiti codul cu cel de sus.

3. Compilati codul si executati metoda main() a noii clase (right-click pe clasa si selectare main()).

 

2.2.2. Constructorii

 

 

 

Constructorul Java este un tip special de functie, care

- are acelasi nume cu numele clasei in care este declarat,

- este utilizat pentru a initializa orice nou obiect de acel tip (stabilind valorile campurilor/ atributelor obiectului, in momentul crearii lui dinamice),

- nu returneazã nici o valoare,

- are aceleasi niveluri de accesibilitate, reguli de implementare a corpului si reguli de supraincarcare a numelui ca si metodele obisnuite.

 

In Java nu este neaparat necesara scrierea unor constructori pentru clase, deoarece un constructor implicit este generat automat de sistemul de executie (DOAR) pentru o clasa care nu declara explicit constructori. Acest constructor nu face nimic (nici o initializare, implementarea lui continand un bloc de cod vid: { }). De aceea, orice initializare dorita explicit impune scrierea unor constructori.

 

Un exemplu de clasa similara celei anterioare, dar care defineste explicit un constructor:

 

 import java.util.Scanner;             // clasa de biblioteca (package) Java
 public class DialogUtilizator02 {     // clasa definita de utilizator
    private Scanner sc;                        // camp Java (atribut) 
    private String prompt; 
    public DialogUtilizator02(String nume) {    // constructor (initializator) 
        this.sc = new Scanner(System.in); 
        this.prompt = nume + "> ";
    } 
    public String nextLine(String text) {      // metode Java (operatii) 
        System.out.print(this.prompt + text);
        return this.sc.nextLine(); 
    } 
    public int nextInt(String text) { 
        System.out.print(this.prompt + text);
        return this.sc.nextInt(); 
    }
    public void println(String text) {   System.out.println(text);   } 
 } 

 

 

In documentatia (API-ul) claselor Java pot fi gasite detalii privind clasa Scanner.

 

In laborator:

1. Tot in proiectul dialog, creati o noua clasa numita DialogUtilizator02  

2. Intrati in codul clasei (in editor), inlocuiti-i codul cu cel dat, apoi compilati-l.

3. Creati un obiect nou, numit d02,  pasandu-i constructorului valoarea "test".

     

4. Executati metoda nextLine() dandu-i ca parametru "Grupa : ". Ce apare in Terminal Window?

5. Inspectati valoarea returnata.    

6. Executati si metodele nextInt() si println() si urmariti efectul lor.

 

2.2.3. Supraincarcarea numelor metodelor si constructorilor

 

Java suporta supraincarcarea numelor (name overloading) pentru metode si constructori. Astfel, o clasa poate avea orice numar de metode cu acelasi nume cu conditia ca listele lor de parametri sa fie diferite.

 

In mod similar, o clasa poate avea orice numar de constructori (acestia avand toti acelasi nume - identic cu numele clasei) cu conditia ca listele lor de parametri sa fie diferite. De exemplu, codul clasei anterioare poate fi completat cu constructorul:

 

     public DialogUtilizator02() {        // constructor (initializator) 
        this.sc = new Scanner(System.in); 
        this.prompt = "IMPLICIT" + "> ";  // echivalent cu: this.prompt = this("IMPLICIT ");    
    } 

 

In laborator:

1. Intrati in codul clasei DialogUtilizator02 (in editor), adaugati constructorul, apoi recompilati.

2. Creati un obiect nou folosind noul constructor. Ce observati?

3. Executati-i metoda println() dandu-i ca parametru "POO". Ce apare in Terminal Window?

4. Creati un obiect nou folosind primul constructor, caruia ii pasati "EXPLICIT".

5. Executati-i metoda println() dandu-i ca parametru "POO". Ce apare in Terminal Window?

 

In laborator:

1. Concepeti si editati codul unei metode noi a clasei DialogUtilizator02, cu semnatura:

         public void println()

    care nu primeste parametru si afiseaza in Terminal Window (folosind System.out.println())

           textul: "Nu am primit nici un parametru".

2. Recompilati clasa si creati un obiect nou folosind noul constructor.

3. Executati noua metoda println(). Ce apare in Terminal Window?

4. Executati din nou vechea metoda println(), cu parametru "x". Ce apare in Terminal Window?

 

2.2.4. Relatii intre clase: asocierea si utilizarea

 

Legãtura este o cale între obiectele care se cunosc (vãd) unul pe altul (îºi pot transmite mesaje – apelurile de metode), pentru aceasta avand referinte unul cãtre celãlalt.

 

Fie clasele Java:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

 public class Point {
    private int x;     
    private int y;
 
    public Point(int abscisa, int ordonata) {
       x = abscisa;
       y = ordonata;
    }
    public void moveTo(int abscisaNoua, int ordonataNoua) {
       x = abscisaNoua;
       y = ordonataNoua;
    }
    public void moveWith(int deplasareAbsc, int deplasareOrd) {
       x = x + deplasareAbsc;
       y = y + deplasareOrd;
    }
    public int getX() {   return x;  }
    public int getY() {   return y;  }
 }

 

1

2

3

4

5

6

7

8

9

 public class UtilizarePoint {
    private static Point punctA;     // referinta, legatura catre un obiect Point
 
    public static void main(String[] args) {            
       punctA = new Point(3, 4);     // alocare si initializare atribut punctA
       punctA.moveTo(3, 5);          // trimitere mesaj moveTo() catre punctA
       punctA.moveWith(3, 5);        // trimitere mesaj moveWith() catre punctA
    }
 }

 

 

Un obiect sau o clasa “vede” un alt obiect daca are o referinta catre el, si astfel ii poate apela metodele. Se spune ca exista o legatura intre obiectul care are referinta catre obiectul referit.

 

De exemplu, clasa UtilizarePoint are o referinta punctA  catre un obiect al clasei Point.

 

Fiecãrei familii de legãturi între obiecte ale aceleiasi clase ii corespunde o relaþie între clasele acelor obiecte.

 

Asocierea este o relatie care exprimã un cuplaj (o dependenta) redus între clase (clasele asociate rãmânând relativ independente). Clasele Point si UtilizarePoint sunt de exemplu intr-o relatie de asociere (cu navigabilitate) unidirectionala:

 

Clasa UtilizarePoint are un atribut punctA de tip Point care permite clasei UtilizarePoint sa trimita mesaje unui obiect (pointA) al clasei Point.

 

 

    private Point punctA;                               // atribut de tip Point

 

Clasa Point in schimb nu are nici o referinta catre clasa UtilizarePoint care sa ii permita trimiterea de mesaje (invocari de metode).

 

Asocierile unidirectionale pot fi considerate relatii de utilizare. Ele se reprezinta prin sageti indreptate pe directia catre care exista referinta (catre care se pot trimite mesaje). Clasa RunDialogUtilizator01 utilizeaza un obiect al clasei DialogUtilizator01:

 

 

 

 

2.3. Studiu de caz: clasele Mesaj si Pachet

2.3.1. Structura de baza a clasei Mesaj: campuri, constructori, metode

 

Clasa Mesaj01 incapsuleaza un obiect de tip String care reprezinta un mesaj de la utilizatorul curent (regrupand textul mesajului cu metodele prin care este controlat accesul la acesta):

 

 public class Mesaj01 {
    private String text;                                 
    public Mesaj01(String text) {         // constructor cu parametru
        this.text = text; 
    }    
    public String getText() {             // obtinerea valorii campului
        return this.text; 
    }        
    public String toString() { 
        return ("Mesaj: " + this.text); 
    } 
    public void display() { 
        System.out.println(this.toString()); 
    } 
    public boolean equals(Object obj) { 
        return this.text.equals(((Mesaj01)obj).text); 
    } 
 }

 

In laborator:

1. Lansati mediul BlueJ.  Inchideti toate proiectele (Ctrl+W). Creati un proiect numit mesaj. 

2. Creati clasa Mesaj01 folosind codul dat mai sus.

3. Compilati codul si creati 3 obiecte tip Mesaj01 - doua dintre ele cu aceleasi valori ale

     campului text si al treilea cu alte valori ale campului text.

4. Inspectati obiectele.

5. Apelati metodele getText(), toString() si display() pentru unul dintre obiecte.

6. Apelati metoda equals() a primului obiect folosind ca parametri celelalte doua obiecte.

 

             

 

In laborator:   

1. In proiectul mesaj creati o noua clasa numita Mesaj02, pornind de la codul Mesaj01:

- adaugati un camp de tip int numit tip,

- adaptati constructorul pentru a initializa si campul numit tip,

- adaugati o metoda pentru obtinerea valorii campului numit tip,

- adaptati metoda toString() pentru a include si campul tip in String-ul returnat

       (de exemplu, pentru un <text> si un <tip> dat, va returna: Mesaj de tip <tip>: <text>),

- adaptati metoda equals(Object obj) pentru a include si comparatia campurilor tip

2. Compilati codul si creati 3 obiecte tip Mesaj02 - doua dintre ele cu aceleasi valori ale

     campului text si al treilea cu alte valori ale campului text.

3. Inspectati obiectele.

4. Apelati metoda toString() pentru unul dintre obiecte.

5. Apelati metoda equals() a primului obiect folosind ca parametri celelalte doua obiecte.

 

 

 

 

 

2.3.2. Supraincarcarea numelor in cazul clasei Mesaj

 

In cazul clasei Mesaj01, supraincarcarea numelui constructorului ar insemna crearea unui constructor suplimentar, de exemplu unul care nu primeste nici un parametru:

 

    public Mesaj01() { this(""); }    // corpul este echivalent cu:  { this.text = ""; }

 

In laborator   

1. Editati codul clasei Mesaj01 adaugand constructorul dat mai sus.

2. Compilati codul si creati 2 obiecte tip Mesaj01, fiecare cu cate un constructor.

3. Apelati metoda equals() a primului obiect folosind ca parametru cel de-al doilea obiect.

 

In laborator:   

1. Editati codul clasei Mesaj02 si adaugati un constructor fara parametri, care sa initializeze cele doua campuri cu niste valori implicite.

2. Compilati codul si creati 2 obiecte tip Mesaj02, fiecare cu cate un constructor.

3. Inspectati obiectele.

4. Apelati metoda equals() a primului obiect folosind ca parametru cel de-al doilea obiect.

 

2.3.3. Relatii intre clase: cazul claselor Mesaj si Pachet

 

Pentru a exemplifica relatia de utilizare intre clase va fi creata o clasa Pachet02 care incapsuleaza un obiect Mesaj02 (regrupand mesajul si sursa lui cu metodele prin care este controlat accesul la acestea):

public class Pachet02 {
    private Mesaj02 mesaj;                                 
    private String sursa;                                 
    public Pachet02(Mesaj02 mesaj, String sursa) { 
        this.mesaj = mesaj; 
        this.sursa = sursa; 
    }    
    public Mesaj02 getMesaj() { return this.mesaj; }        
    public String getSursa()  { return this.sursa; }        
    public String toString() { 
        return ("Pachetul de la " + this.sursa + " contine: " + this.mesaj); 
    } 
    public boolean equals(Object obj) { 
        return (this.mesaj.equals(((Pachet02)obj).mesaj)) &&
               (this.sursa.equals(((Pachet02)obj).sursa)); 
    } 
 }

 

Optional, in laborator:                                                                                     

1. In proiectul mesaj creati o noua clasa numita Pachet02, folosind codul de mai sus.

2. Compilati codul si creati mai intai un obiect tip Mesaj02 si apoi un obiect tip Pachet02

     (pasandu-i constructorului Pachet02(Mesaj02 mesaj, String sursa) obiectul tip Mesaj02).

 

      

 

Optional, in laborator:                                   

1. Inspectati ambele obiecte.

 

    

 

 

Optional, in laborator:                                    

1. Apelati metodele getMesaj(), getSursa() si toString() pentru obiectul tip Pachet02.

2. Creati un nou obiect tip Pachet02.

3. Apelati metoda equals() a primului obiect folosind ca parametru al doilea obiect tip Pachet02.

 

In cazul clasei Pachet02, supraincarcarea numelui constructorului ar insemna crearea unui constructor suplimentar, de exemplu unul cu semnatura:

 

    public Pachet02(Mesaj02 mesaj) 

 

Pentru a obtine numele de cont in care se lucreaza ("user.name") se poate utiliza apelul :

 

    String numeUtilizator = System.getProperties().getProperty("user.name");

 

In documentatia (API-ul) claselor Java pot fi gasite si alte proprietati care pot fi obtinute cu apelul System.getProperties().getProperty() (java.home, java.class.path, os.name, user.home).

 

Tema suplimentara:

1. Editati codul clasei Pachet02 si adaugati un constructor cu semnatura de mai sus, care:

- sa initializeze campul numit mesaj cu parametrul primit,

- sa initializeze campul numit sursa cu numele de cont in care se lucreaza (vezi mai sus).

2. Compilati codul si creati un obiect tip Mesaj02.

3. Creati 2 obiecte tip Pachet02, fiecare cu cate un constructor. Inspectati obiectele.

4. Care este valoarea campului sursa in cazul obiectului creat cu constructorul cu un parametru?

 

O clasa Java pentru testarea claselor Pachet02 si Mesaj02:

 

 public class UtilizarePachet02 {
    public static void main(String[] args) {
        Pachet02 p = new Pachet02();
        System.out.println(p.toString());
    }
 }

 

Optional, in laborator:                              

1. In proiectul mesaj creati o noua clasa numita UtilizarePachet02, folosind codul de mai sus.

2. Compilati codul. Ce observati?

3. Cum puteti rescrie codul clasei UtilizarePachet02 pentru a elimina eroarea la compilare?

4. Dupa corectura, deschideti succesiv in editor clasele UtilizarePachet02, Pachet02 si Mesaj02 si modificati optiunea Implementation (aflata in dreapta-sus) in Interface.

5. Studiati continutul paginilor respective.

 

 

\

2.4. Studiu de caz: clasele Grupa, Student, DatePersonale si SituatieCurs

2.4.1. Clasele DatePersonale si SituatieCurs si actualizarea clasei Student

 

Sa presupunem ca dorim sa modificam codul clasei Student care abstractiza un student real, introducand detalii suplimentare referitoare la Student ca persoana, pe langa campul nume.

De exemplu, putem inlocui campul nume de tip String cu un camp date de un tip nou, DatePersonale, care va fi o noua clasa ce va contine pe langa un camp nume de tip String si campurile initiale si prenume de tip String si anNastere de tip int. Codul noii clasei va fi:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

public class DatePersonale {

   // Campuri ascunse

   private String nume;

   private String initiale;

   private String prenume;

   private int anNastere;

 

   // Constructori

   public DatePersonale(String n, String i, String p, int an) {

      nume = new String(n);      // copiere „hard” a obiectelor primite ca parametri,

      initiale = new String(i);  // adica se copiaza obiectul camp cu camp,

      prenume = new String(p);   // nu doar referintele ca pana acum

      anNastere = an;

   }

   // Interfata publica si implementarea ascunsa

   public String getNume() {      return (nume);   }

   public String getPrenume() {   return (prenume);   }

   public int getAnNastere() {    return (anNastere);   }

   public String toString() {    // forma „String” a campurilor obiectului

      return (nume + " " + initiale + " " + prenume + " (" + anNastere + ")");

   }

}

 

De asemenea, presupunem ca dorim sa modificam codul clasei Student regrupand elementele pereche ale campurilor cursuri si rezultate (care sunt tablouri) in obiecte ale unei clase noi, SituatieCurs. Vom inlocui in clasa Student tablourile cursuri cu elemente de tip String si rezultate cu elemente de tip int, cu un singur tablou, cursuri, cu elemente de tip SituatieCurs.

Cele doua clase noi pot fi reprezentate in UML (      = acces private,     = acces public) astfel:

 

 

Codul Java al noii clasei va fi:                

 

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

public class SituatieCurs {

   // Campuri ascunse

   private int nota = 0;                            // initializare implicita

   private String denumire;

 

   // Constructor

   public SituatieCurs(String d) { denumire = new String(d); }     // copiere „hard”

                                                   // se initializeaza doar denumire

   // Interfata publica si implementarea ascunsa

   public void notare(int n) {     nota = n; }     // se adauga nota

   public int nota() {             return(nota); } // se returneaza nota

   public String toString() {                      // forma „String” a campurilor

      if (nota==0) return ("Disciplina " + denumire + " nu a fost notata");

      else return("Rezultat la disciplina " + denumire + ": " + nota);

   }

}

 

 

 

 

In cele doua clase, se observa ca se foloseste copierea “hard” a obiectelor primite ca parametri, adica crearea unor copii ale obiectelor argument, camp cu camp, nu doar copierea referintelor.

In clasa SituatieCurs nu am utilizat metode de tip getCamp() si setCamp(). Metoda nota()ar fi putut fi denumita getNota() iar metoda notare() ar fi putut fi denumita setNota().

Printre metodele declarate regasim si toString(), cu scopul de a returna sub forma de String informatiile pe care le incapsuleaza obiectul caruia i se aplica. Nota initiala 0 inseamna notei (notarea poate incepe doar cu 1). De aceea toString() returneaza diferit pentru valori nule/nenule.

 

Vom rescrie acum codul Java al clasei Student pentru a incorpora schimbarile anuntate.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

/**
   * Incapsuleaza informatiile despre un Student. Permite testarea locala.
   * @version 1.3
   */
  public class Student {

   // Campuri ascunse

   private DatePersonale date;

   private SituatieCurs[] cursuri;

   private int numarCursuri = 0;             // initializare implicita

  

   // Constructori

   public Student(String nume, String initiale, String prenume, int anNastere) {

      date = new DatePersonale(nume, initiale, prenume, anNastere); // copiere „hard”

      cursuri = new SituatieCurs[10];        // se initializeaza doar date si cursuri

   }

 

   // Interfata publica si implementarea ascunsa (include punct intrare program)

   public void addCurs(String nume) {        // se adauga un nou curs

      cursuri[numarCursuri++] = new SituatieCurs(nume);

   }

   public void notare(int numarCurs, int nota) {

      cursuri[numarCurs].notare(nota);       // se adauga nota cursului specificat

   }

   public String toString() {                // forma „String” a campurilor

      String s = "Studentul " + date + " are urmatoarele rezultate:\n";

      for (int i=0; i<numarCursuri; i++)   s = s + cursuri[i].toString() + "\n";

      return (s);

   }

   public static void main(String[] args) {

      // Crearea unui nou Student, initializarea campurilor noului obiect

      Student st1 = new Student("Xulescu", "Ygrec", "Z.", 1987);

      st1.addCurs("CID");

      st1.addCurs("MN");

      st1.notare(0, 8);

      // Utilizarea informatiilor privind Studentul

      System.out.println(st1.toString());    // afisarea formei „String” a campurilor

   }

 

Regasim copierea “hard” a obiectelor si metoda toString(). Tabloul cursurilor este initial gol, rand pe rand fiind adaugate cursuri noi (si e incrementat numarul lor).

In UML avem asocierile (clasa Student utilizeaza DatePersonale si SituatieCurs):

 

           

 

Clasa are o metoda main() cu rolul de a testa lucrul cu obiectele Student. Executia ei conduce la:

     Studentul Xulescu Z. Ygrec (1987) are urmatoarele rezultate:

     Rezultat la disciplina CID: 8

     Disciplina MN nu a fost notata

 

 

2.4.2. Clasa Grupa

 

Sa presupunem ca dorim sa scriem codul unei clase noi numita Grupa care sa abstractizeze o grupa de studenti in cadrul programului care gestioneaza informatii intr-o universitate, facultate, etc.

 

Clasa va avea campuri separate pentru serie, de care tine, si numar, care o identifica (cele doua ar putea forma o alta clasa, de exemplu InfoGrupa) si un tablou pentru referinte spre studenti.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

public class Grupa {

   // Campuri ascunse

   private int numar;

   private String serie;

   private Student[] studenti;

  

   // Constructori

   public Grupa(int nr, String sr) {         // se initializeaza doar serie si numar

      numar = nr; serie = new String(sr);    // copiere „hard” pentru serie

   }

 

   // Interfata publica si implementarea ascunsa (include punct intrare program)

   public void addStudenti(Student[] st) {   // se adauga tabloul de studenti

      studenti = new Student[st.length];

      System.arraycopy (st, 0, studenti, 0, st.length);  // copiere „hard” a tabloului

   }

   public String toString() {

      String g = "\nRezultatele grupei " + numar + serie + ":\n";

      for (int i=0; i<studenti.length; i++)

        g = g + studenti[i].toString() + "\n";

      return (g);

   }

   public static void main(String[] args) {

      // Crearea unui nou Student, initializarea campurilor noului obiect

      Student st1 = new Student("Xulescu", "A.", "Ygrec", 1987);

      st1.addCurs("CID");

      st1.addCurs("MN");

      st1.notare(0, 8);

      // Crearea unui nou Student, initializarea campurilor noului obiect

      Student st2 = new Student("Zulescu", "B.", "Ics", 1988);

      st2.addCurs("CID");

      st2.addCurs("MN");

      st2.notare(1, 9);

      // Crearea unei noi Grupe, initializarea campurilor noului obiect

      Grupa g1 = new Grupa(424, "A");

      Student[] st = {st1, st2};

      g1.addStudenti(st);

      // Utilizarea informatiilor privind Grupa

      System.out.println(g1.toString());     

   }

}

 

Asocierile in UML (clasa Grupa utilizeaza Student):

 

    

 

Pentru copiere „hard” a tablourilor (element cu element), clasa System ofera metoda arraycopy(), care copiaza un subtablou din tabloul sursa src, de lungime length, incepand de la index srcPos, in tabloul destinatie dest, la index destPos.

Semnatura arraycopy() este:            

 

    static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

 

Metoda main() testeaza lucrul cu obiectele Grupa si Student. Executia ei are ca efect:                      

 

     Rezultatele grupei 424A:

     Studentul Xulescu A. Ygrec (1987) are urmatoarele rezultate:

     Rezultat la disciplina CID: 8

     Disciplina MN nu a fost notata

 

     Studentul Zulescu B. Ics (1988) are urmatoarele rezultate:

     Disciplina CID nu a fost notata

     Rezultat la disciplina MN: 9

 

2.5. Extinderea prin mostenire

2.5.1. Generalizarea si specializarea claselor

 

Generalizarea reprezinta extragerea elementelor comune (atribute, operaþii ºi constrângeri) ale unui ansamblu de clase într-o nouã clasã mai generalã numitã superclasã (care reprezinta o abstracþie a subclaselor ei).

 

Rezulta o ierarhie in care arborii de clase sunt construiþi pornind de la frunze, atunci cand elementele modelului au fost identificate, obþinandu-se o descriere generica si flexibila a soluþiilor.

 

Generalizarea semnificã relatia de tip "este un" atunci cand un obiect dintr-o clasa din ansamblul generalizat este in acelasi timp si obiect al superclasei, si de tip "este un fel de" atunci cand un obiect dintr-o clasa din ansamblul generalizat este doar aproximativ si obiect al superclasei (aproximatia venind din rescrierile codurilor operate in clasa generalizata).

 

Generalizarea actioneaza in orientarea spre obiecte la doua niveluri:

- clasele sunt generalizari ale ansamblurilor de obiecte (un obiect este de felul definit de o clasa),

- superclasele sunt generalizari ale unor clase (obiectele de felul specificat intr-o clasa sunt in acelasi timp si de felul specificat in superclasa).

Orientarea spre obiecte (OO) presupune ambele tipuri de generalizare, iar limbajele orientate spre obiecte sunt acelea care ofera ambele mecanisme de generalizare. Limbajele care ofera doar constructii numite obiecte (si eventual clase) se pot numi limbaje care lucreaza cu obiecte (si eventual clase).

 

Specializarea claselor reprezinta capturarea particularitãþilor unui ansamblu de obiecte nediscriminate ale unei clase existente, noile caracteristici fiind reprezentate într-o nouã clasã mai specializatã, denumitã subclasã.

 

Specializarea usureaza extinderea coerentã a unui ansamblu de clase, noile cerinþe fiind încapsulate în subclase care extind funcþiile existente.

 

 

În elaborarea unei ierarhii de clase, se cer diferite aptitudini sau competenþe:

- pentru generalizare: capacitate de abstractizare, independentã de cunoºtinþele tehnice,

- pentru specializare: experienþã si cunoºtinþe aprofundate într-un domeniu particular.

 

2.5.2. Mostenirea. Rescrierea codului metodelor (overriding)

 

Moºtenirea este o tehnicã de generalizare oferitã de limbajele de programare orientate spre obiecte pentru a construi o clasã pornind de la una sau mai multe alte clase, partajând atributele si operaþiile (campurile si metodele, in Java) într-o ierarhie de clase.

 

In limbajul Java, orice clasa care nu extinde in mod explicit (prin mostenire) o alta clasa Java, extinde (prin mostenire) in mod implicit clasa Object (radacina ierarhiei de clase Java), clasa care contine metodele necesare tuturor obiectelor create din ierarhia de clase Java. Urmatoarele doua declaratii de clasa sunt echivalente:

 

 

    class NumeClasa {                // urmeaza corpul clasei ...

 

 

 

    class NumeClasa extends Object { // urmeaza corpul clasei ...

 

Notatia UML pentru extinderea prin mostenire este o linie care uneste clasa extinsa (de baza, superclasa) de clasa care extinde (subclasa), linie terminata cu un triunghi in capatul dinspre clasa de baza. Diagrama UML corespunzatoare codului Java anterior:

Metoda toString(), metoda care are ca scop returnarea sub forma de String a informatiilor pe care le incapsuleaza obiectul caruia i se aplica aceasta metoda.

1. In cazul claselor de biblioteca Java, metoda toString() returneaza ansamblul valorilor curente ale atributelor obiectului.

 

2. In cazul claselor scrise de programator, in mod implicit metoda toString() returneaza numele clasei careia ii apartine obiectul urmat de un cod alocat acelui obiect (hashcode).

Implementarea implicita a metodei toString() este urmatoarea:

 

1

2

3

4

5

6

7

  // Implementarea implicita a metodei toString(),

  // mostenita de la clasa Object

 

  public String toString() {

     // (nu returneaza continutul ci numele clasei si codul obiectului!)

     return getClass().getName() + "@" + Integer.toHexString(hashCode());

  }

 

3. In cazul in care programatorul doreste returnarea informatiilor incapsulate in obiect, trebuie specificat in mod explicit un nou cod (o noua implementare) pentru metoda toString(). Acest lucru se obtine adaugand clasei din care face parte acel obiect o metoda cu declaratia:

 

 

    public String toString() { // urmeaza corpul metodei ...

 

metoda care se spune ca rescrie (overrides) codul metodei cu acelasi nume din clasa extinsa (in acest caz clasa Object).

 

Dupa adaugarea acestei metode, apelul toString() va conduce la executia noului cod, pe cand apelul super.toString() va duce la executia codului din clasa extinsa (superclasa, Object).

 

 

Metoda equals() are ca scop compararea continutului obiectului primit ca parametru cu continutul obiectului caruia i se aplica aceasta metoda, returnand valoarea booleana true in cazul egalitatii si valoarea booleana false in cazul inegalitatii celor doua obiecte.

 

1. In cazul claselor de biblioteca Java, metoda equals() compara ansamblul valorilor curente ale atributelor obiectului (continutul sau starea obiectului).

 

2. In cazul claselor scrise de programator, in mod implicit metoda equals() compara referinta obiectului caruia i se aplica aceasta metoda cu referinta obiectului pasat ca parametru. Implementarea implicita a metodei equals() este urmatoarea:

 

1

2

3

4

5

6

  // Implementarea implicita a metodei equals(),

  // mostenita de la clasa Object

 

  public boolean equals(Object obj) {

    return (this == obj);     // (nu compara continutul ci referintele!!!)

  }

 

3. In cazul in care programatorul doreste compararea informatiilor incapsulate in obiect, (ansamblul valorilor curente ale atributelor obiectului) trebuie specificat in mod explicit un nou cod (o noua implementare) pentru metoda equals(). Acest lucru se obtine adaugand clasei din care face parte acel obiect o metoda cu declaratia:

 

 

    public boolean equals(Object obj) { // urmeaza corpul metodei ...

 

metoda care rescrie (overrides) codul metodei cu acelasi nume din clasa extinsa (Object).

 

Dupa adaugarea acestei metode, apelul equals() va conduce la executia noului cod, pe cand apelul super.equals()duce la executia codului din clasa extinsa (in acest caz codul din Object).

 

 

2.6. Studiu de caz: clasele Persoana, Student, Profesor, DatePersonale, SituatieCurs, si StudentMaster

 

2.6.1. Clasele Persoana si Profesor si actualizarea clasei Student

 

 

 

Sa presupunem ca dorim sa adaugam o clasa Profesor care abstractizeaza un profesor real, prin intermediul unui camp date de tip DatePersonale, si a unui camp titlu de tip String.

 

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

 /**
   * Incapsuleaza informatiile despre un Profesor. Permite testarea locala.
   * @version 1.3
   */
  public class Profesor {

   // Campuri ascunse

   private DatePersonale date;

   private String titlu;

  

   // Constructori

   public Profesor(String nume, String initiale, String prenume, int anNastere) {

      date = new DatePersonale(nume, initiale, prenume, anNastere); // copiere „hard”

   }

 

   // Interfata publica si implementarea ascunsa (include punct intrare program)

   public void setTitlu(String t) { 

      titlu = new String(t);      // copiere „hard” a obiectului primit ca parametru

   }

   public String toString() {                // forma „String” a campurilor

      return ("Profesorul " + date + " are titlul " + titlu);

   }

   public static void main(String[] args) {

      // Crearea unui nou Profesor, initializarea campurilor noului obiect

      Profesor pr = new Profesor("Nulescu", "Ion", "A.", 1960);

      pr.setTitlu("Lector Dr.");

      // Utilizarea informatiilor privind Profesorul

      System.out.println(pr.toString());    // afisarea formei „String” a campurilor

   }

  }

 

Se observa ca avem un camp (date) comun cu clasa Student.

 

Putem crea o clasa Persoana care sa contina acest element comun, rescriind apoi codurile claselor Profesor si Student pentru a extinde clasa Persoana (si a-i refolosi campul date). Codul noii clase Persoana va fi:

 

 

 

 

 

 

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

 /**
   * Incapsuleaza informatiile despre o Persoana. Permite testarea locala.
   * @version 1.4
   */
 public class Persoana {

   // Campuri ascunse

   protected DatePersonale date;

  

   // Constructori

   public Persoana(String nume, String initiale, String prenume, int anNastere) {

      date = new DatePersonale(nume, initiale, prenume, anNastere); // copiere „hard”

   }

   // Interfata publica si implementarea ascunsa (include punct intrare program)

   public String toString() {                  // forma „String” a campurilor

      return (super.toString());

   }

   public static void main(String[] args) {

      // Crearea enei noi Persoane, initializarea campurilor noului obiect

      Persoana p = new Persoana("Julescu", "Ion", "C.", 1965);

      // Utilizarea informatiilor privind Profesorul

      System.out.println(p.toString());    // afisarea formei „String” a campurilor

   }

 }

 

Vom rescrie acum codul clasei Profesor pentru a incorpora schimbarile anuntate.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

 /**
   * Incapsuleaza informatiile despre un Profesor. Permite testarea locala.
   * @version 1.4
   */
  public class Profesor extends Persoana {

   // Campuri ascunse

   protected String titlu;

  

   // Constructori

   public Profesor(String nume, String initiale, String prenume, int anNastere) {

      super(nume, initiale, prenume, anNastere); // apel constructor supraclasa

   }                                             // (reutilizare cod)

 

   // Interfata publica si implementarea ascunsa

   public void setTitlu(String t) { 

      titlu = new String(t);       // copiere „hard” a obiectului primit ca parametru

   }

 

   public String toString() {                // forma „String” a campurilor

      return ("Profesorul " + date + " are titlul " + titlu);

   }

   public static void main(String[] args) {

      // Crearea unui nou Profesor, initializarea campurilor noului obiect

      Profesor pr = new Profesor("Nulescu", "Ion", "A.", 1960);

      pr.setTitlu("Lector Dr.");

      // Utilizarea informatiilor privind Profesorul

      System.out.println(pr.toString());    // afisarea formei „String” a campurilor

   }

  }

 

 

Vom rescrie acum codul clasei Student pentru a incorpora schimbarile anuntate.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

/**
   * Incapsuleaza informatiile despre un Student. Permite testarea locala.
   * @version 1.4
   */
  public class Student extends Persoana {

   // Campuri ascunse

   protected SituatieCurs[] cursuri;

   protected int numarCursuri = 0;             // initializare implicita

  

   // Constructori

   public Student(String nume, String initiale, String prenume, int anNastere) {

      super(nume, initiale, prenume, anNastere); // apel constructor supraclasa

      cursuri = new SituatieCurs[10];        // se initializeaza doar date si cursuri

   }

 

   // Interfata publica si implementarea ascunsa (include punct intrare program)

   public void addCurs(String nume) {        // se adauga un nou curs

      cursuri[numarCursuri++] = new SituatieCurs(nume);

   }

 

   public void notare(int numarCurs, int nota) {

      cursuri[numarCurs].notare(nota);       // se adauga nota cursului specificat

   }

 

   public String toString() {                // forma „String” a campurilor

      String s = "Studentul " + date + " are urmatoarele rezultate:\n";

      for (int i=0; i<numarCursuri; i++)   s = s + cursuri[i].toString() + "\n";

      return (s);

   }

 

   public static void main(String[] args) {

      // Crearea unui nou Student, initializarea campurilor noului obiect

      Student st1 = new Student("Xulescu", "Ygrec", "Z.", 1987);

      st1.addCurs("CID");

      st1.addCurs("MN");

      st1.notare(0, 8);

      // Utilizarea informatiilor privind Studentul

      System.out.println(st1.toString());    // afisarea formei „String” a campurilor

   }

  }

 

Codul clasei DatePersonale ramane nemodificat:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

public class DatePersonale {

   // Campuri ascunse

   private String nume;

   private String initiale;

   private String prenume;

   private int anNastere;

 

   // Constructori

   public DatePersonale(String n, String i, String p, int an) {

      nume = new String(n);      // copiere „hard” a obiectelor primite ca parametri,

      initiale = new String(i);  // adica se copiaza obiectul camp cu camp,

      prenume = new String(p);   // nu doar referintele ca pana acum

      anNastere = an;

   }

   // Interfata publica si implementarea ascunsa

   public String getNume() {      return (nume);   }

   public String getPrenume() {   return (prenume);   }

   public int getAnNastere() {    return (anNastere);   }

   public String toString() {    // forma „String” a campurilor obiectului

      return (nume + " " + initiale + " " + prenume + " (" + anNastere + ")");

   }

}

 

Codul clasei SituatieCurs ramane nemodificat:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

public class SituatieCurs {

   // Campuri ascunse

   private int nota = 0;                            // initializare implicita

   private String denumire;

 

   // Constructor

   public SituatieCurs(String d) { denumire = new String(d); }     // copiere „hard”

                                                   // se initializeaza doar denumire

   // Interfata publica si implementarea ascunsa

   public void notare(int n) {     nota = n; }     // se adauga nota

   public int nota() {             return(nota); } // se returneaza nota

   public String toString() {                      // forma „String” a campurilor

      if (nota==0) return ("Disciplina " + denumire + " nu a fost notata");

      else return("Rezultat la disciplina " + denumire + ": " + nota);

   }

}

 

2.6.2. Clasa StudentMaster

 

Sa presupunem ca dorim sa scriem codul unei clase noi numita StudentMaster care sa abstractizeze un anumit subtip al tipului Student, prin adaugarea la codul clasei Student a unui camp numit specializare de tip String.

Relatiile de utilizare (linie punctata) si mostenire (sageti cu triunghi in capat) in UML:

 

Putem scrie codul acestei clase care extinde clasa Student astfel:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

/**
   * Incapsuleaza informatiile despre un Student. Permite testarea locala.
   * @version 1.4
   */
  public class StudentMaster extends Student {

   // Campuri ascunse

   private String specializare;

  

   // Constructori

   public StudentMaster(String nume, String initiale, String prenume, int anNastere) {

      super(nume, initiale, prenume, anNastere); // apel constructor supraclasa

   }

 

   // Interfata publica si implementarea ascunsa (include punct intrare program)

   public void setSpecializare(String spec) {        // se stabileste specializarea

      specializare = new String(spec);   // copiere „hard” a obiectului primit

   }

   public String toString() {                // forma „String” a campurilor

      String s = "Studentul " + date + " cu specializarea " + specializare +

                                                " are urmatoarele rezultate:\n";

      for (int i=0; i<numarCursuri; i++)   s = s + cursuri[i].toString() + "\n";

      return (s);

   }

   public static void main(String[] args) {

      // Crearea unui nou Student, initializarea campurilor noului obiect

      StudentMaster sm = new StudentMaster("Rulescu", "Ygrec", "T.", 1983);

      sm.addCurs("Securitate Retele");

      sm.addCurs("Servicii Web");

      sm.setSpecializare("Retele si Software de Telecomunicatii");

      sm.notare(0, 9);

      // Utilizarea informatiilor privind Studentul

      System.out.println(sm.toString());    // afisarea formei „String” a campurilor

   }

  }

 

Anexe                                                                  

1. Mediul de dezvoltare JCreator

 

O alternativa utila la BlueJ (http://www.bluej.org/) este mediul JCreator (prezentare, how to 1, how to 2, caracteristici, http://www.jcreator.com/).

 

Principalele caracteristici ale mediului JCreator:

- organizeaza proiectele cu usurinta folosind o interfata care se aseamana cu Microsoft Visual Studio.

- permite definirea propriilor scheme color in XML, oferind variante de organizare a codului.

- impacheteaza proiectele existente si permite folosirea de profile JDK diferite.

- browser-ul sau faciliteaza vizualizarea proiectelor.

- depanarea se face simplu, cu o interfata intuitiva, fara a fi nevoie de prompt-uri DOS.

- face aceasta configurarea Classpath in locul utilizatorului.

- permite modificarea interfetei utilizatorului dupa dorinta acestuia.

- permite setarea mediului de rulare a aplicatiilor ca applet-uri, intr-un mediu JUnit sau consola DOS.

- necesita putine resurse din partea sistemului si totusi ofera o viteza foarte buna.

 

Interfata grafica a mediului Jcreator 3.50 LE:

2. Mediul de dezvoltare NetBeans IDE BlueJ Edition

 

Interfata grafica a mediului NetBeans IDE 5.5.1 BlueJ Edition:

 

Mediul de dezvoltare NetBeans IDE BlueJ Edition este un hibrid intre NetBeans si BlueJ, un IDE modular scris in limbajul de programare Java. Cateva tutoriale si alte documentatii: pagina de Tutoriale, pagina de blog A note on how to enable code completion a lui Greg Sporar (04.10.2006), un video despre NetBeans/BlueJ creat de Sun Developer Network, un set de note de laborator (Lab Notes to help transition from BlueJ), tutorialul An extended tutorial de Dana Nourie (09.2006), tutorialul Zuul Everywhere with NetBeans 5.5 de Brian Leonard (30.05.2007).

Kitul de instalare NetBeans IDE 5.5.1 BlueJ Edition poate fi gasit la adresele: versiunea Windows: NetBeansBlueJ-5.5.1-win-ml.exe ,  versiunea Linux: NetBeansBlueJ-5.5.1-linux-ml.bin

 

 

2.7. Teme pentru acasa                                   

 

 

Temele de casa pentru data viitoare (predate pe hartie, scrise de mana sau ca listing):

 

I. Codurile sursa ale unor clase create dupa modelul din sect 3.4 (DatePersonale, pag 9, SituatieCurs, pag 9, si Grupa, pag 11) cu urmatoarea specificatie generala:

 

(1) Va fi creata o clasa care este utilizata de clasa primita ca tema la prima lucrare, cu numele alocat din tabelul care urmeaza, dupa modelul claselor DatePersonale si SituatieCurs, fie prin regruparea fie prin detalierea unor campuri ale clasei primite ca tema la prima lucrare,

- noua clasa va contine 2-3 campuri private, un constructor public, 2-3 metode publice pentru lucrul cu campurile si o metoda publica de tip toString(),

 

(2) Va fi modificata clasa primita ca tema la prima lucrare pentru a putea utiliza obiecte ale clasei nou create, si i se va adauga o metoda publica toString(),

- metoda ei main() va afisa ceea ce returneaza metoda toString(),

 

(3) Va fi creata o clasa care utilizeaza clasa primita ca tema la prima lucrare, cu numele alocat din tabelul care urmeaza, dupa modelul clasei Grupa,

- noua clasa va contine 2-3 campuri private, un constructor public, 2-3 metode publice pentru lucrul cu campurile si o metoda publica de tip toString(),

- metoda ei main() va afisa ceea ce returneaza metoda toString(),

 

 

Numele claselor propuse corespunzatoare clasei primite ca tema la prima lucrare sunt:

 

 

Clasa care utilizeaza

(ca Grupa)

Clasa

initiala

(ca Student)

Clasa

utilizata (ca DatePersonale)

 

 

Clasa care utilizeaza

(ca Grupa)

Clasa

initiala

(ca Student)

Clasa

utilizata (ca DatePersonale)

1

Cutie

Scrisoare + Vedere

Adresa

 

8

Retea

PC +

Laptop

Ecran

2

Dulap

Mapa +

Geanta

Compartiment

 

9

Parcare

Motocicleta + Bicicleta

Roata

3

Flota

Elicopter + Avion

Elice

 

10

Desktop

MonitorCuTub + MonitorLCD

Buton

4

Garaj

Masina + Camion

Sofer

 

11

Disciplina

Seminar + Laborator

Tema

5

Raft

Revista + Carte

Pagina

 

12

Cartier

Bloc +

Vila

Apartament

6

Sala

Banca + Catedra

Sertar

 

13

Cusca

Caine +

 Pisica

Blana

7

Bloc

Garsoniera +Apartament

Bucatarie

 

14

Portofel

CardDebit + CardCredit

Sigla

 

 

Membrii fiecarui grup vor crea fie coduri separate care sunt utilizate de / utilizeaza clasa aleasa data trecuta, fie un cod comun care este utilizat de / utilizeaza ambele clase ale grupului (varianta recomandata).

 

 

II. Codurile sursa ale unor clase create dupa modelul din sect 4.5 (Persoana, Profesor, Student, si StudentMaster) cu urmatoarea specificatie generala:

 

(1) Va fi creata o clasa care are elemente comune cu clasa primita ca tema la prima lucrare (actualizata conform punctului I), cu numele alocat din tabelul care urmeaza, dupa modelul clasei Profesor:

- noua clasa va contine 1-2 campuri protected, un constructor public, 1-2 metode publice pentru lucrul cu campurile si o metoda publica de tip toString(),

 

(2) Va fi creata o clasa care contine elementele comune ale clasei primite ca tema la prima lucrare (actualizata conform punctului I) si a clasei nou create la punctul (1) – adica le generalizeaza, cu numele alocat din tabelul care urmeaza, dupa modelul clasei Persoana:

- noua clasa va contine campurile comune protected, un constructor public, si o metoda publica de tip toString(),

 

(3) Va fi modificata clasa primita ca tema la prima lucrare (actualizata conform punctului I) pentru a extinde clasa nou creata la punctul (2) si a-i reutiliza campurile si codul constructorului, campurile ei fiind declarate protected

 

(4) Va fi modificata clasa de la punctul (1) pentru a extinde clasa nou creata la punctul (2) si a-i reutiliza campurile si codul constructorului, campurile ei fiind declarate protected

 

(5) Va fi creata o clasa care extinde (specializeaza) clasa primita ca tema la prima lucrare (actualizata conform punctului I), cu numele alocat din tabelul care urmeaza, dupa modelul clasei StudentMaster,

- noua clasa va contine 1-2 campuri noi private, un constructor public, 1-2 metode publice pentru lucrul cu campurile si o metoda publica de tip toString(),

- metoda ei main() va afisa ceea ce returneaza metoda toString(),

 

 

Numele claselor propuse corespunzatoare numerelor de ordine alocate la prima lucrare sunt:

 

 

Clasa extinsa

(ca Persoana)

Clasa initiala (ca Student)

si o pereche a ei (ca Profesor)

Clasa care extinde

(ca StudentMaster)

1

Corespondenta

Scrisoare + Vedere

ScrisoareRecomandata + VedereAlbNegru

2

Bagaj

Mapa + Geanta

MapaCuFermoar + GeantaVoiaj

3

VehiculAerian

Elicopter + Avion

ElicopterMilitar + AvionUtilitar

4

Vehicul

Masina + Camion

Berlina + TIR

5

Publicatie

Revista + Carte

RevistaCalculatoare + CarteTelefon

6

Mobilier

Banca + Catedra

BancaDubla + CatedraCuSertare

7

Locuinta

Garsoniera +Apartament

GarsonieraDecomandata + ApartamentSemicomandat

8

SistemDeCalcul

PC + Laptop

PCIBM + LaptopDell

9

VehiculPeDouaRoti

Motocicleta + Bicicleta

MotocicletaCuAtas + MountainBike

10

Monitor

MonitorCuTub + MonitorLCD

MonitorCuTubPlat + MonitorLCDSamsung

11

Activitate

Seminar + Laborator

SeminarFinal + ColocviuLaborator

12

Cladire

Bloc + Vila

BlocGarsoniere + VilaProtocol

13

Animal

Caine + Pisica

Dalmatian + PisicaBirmaneza

14

Card

CardDebit + CardCredit

CardDebitVisa + CardCreditMasterCard

 

 

Membrii fiecarui grup vor crea fie coduri separate, fie un cod comun (varianta recomandata).