Clase si metode abstracte
Clasele abstracte sunt utilizate pentru a declara caracteristici comune unor subclase. O clasa abstracta nu poate fi instantiata. Ea poate fi utilizata numai ca si superclasa pentru alte clase care extind clasa abstracta. Clasele abstracte sunt declarate prin intermediul modificatorului abstract.
O clasa abstracta poate contine atribute, care descriu caracteristicile clasei, si metode, care descriu actiunile care pot fi desfasurate de clasa. De asemenea, o clasa abstracta poate include metode care nu sunt implementate. Aceste metode detin doar declaratie si poarta numele de metode abstracte. Ca si in cazul claselor abstracte, metodele abstracte sunt insotite in declaratia lor de modificatorul abstract.
Daca o clasa contine metode abstracte, atunci ea trebuie sa fie declarata abstracta.
package ro.virtualcampus.obiectgrafic; | |
public abstract class ObiectGrafic { | |
protected double x, y; | |
public ObiectGrafic() { | |
x = 0; | |
y = 0; | |
} | |
public ObiectGrafic(double x, double y) { | |
this.x = x; | |
this.y = y; | |
} | |
@Override | |
public String toString() { | |
return "ObiectGrafic [x=" + x + ", y=" + y + "]"; | |
} | |
public abstract double aria(); | |
public abstract double perimetrul(); | |
public double getX() { | |
return x; | |
} | |
public void setX(double x) { | |
this.x = x; | |
} | |
public double getY() { | |
return y; | |
} | |
public void setY(double y) { | |
this.y = y; | |
} | |
} |
Toate clasele concrete derivate dintr-o clasa abstracta trebuie sa implementeze metodele abstracte prezente in clasa de baza.
Intr-o aplicatie Java care construieste obiecte grafice pot fi definite cercuri, dreptunghiuri, patrate, etc. Aceste categorii de obiecte grafice sunt implementate prin intermediul unor clase concrete. Clasa abstracta care traseaza caracteristicile de baza ale obiectelor grafice este definita mai sus (ObiectGrafic).
package ro.virtualcampus.obiectgrafic; | |
public class Cerc extends ObiectGrafic { | |
private double raza; | |
public Cerc(double raza) { | |
super(); | |
this.raza = raza; | |
} | |
public Cerc(double x, double y, double raza) { | |
super(x, y); | |
this.raza = raza; | |
} | |
@Override | |
public String toString() { | |
return "Cerc [raza=" + raza + ", x=" + x + ", y=" + y + "]"; | |
} | |
@Override | |
public double aria() { | |
return java.lang.Math.PI * raza * raza; | |
} | |
@Override | |
public double perimetrul() { | |
return 2 * java.lang.Math.PI * raza; | |
} | |
public double getRaza() { | |
return raza; | |
} | |
public void setRaza(double raza) { | |
this.raza = raza; | |
} | |
} |
Subclasele concrete (Cerc, Dreptunghi) ofera implementari proprii ale metodelor abstracte, aria() si perimetrul(), declarate in superclasa ObiectGrafic.
package ro.virtualcampus.obiectgrafic; | |
public class Dreptunghi extends ObiectGrafic { | |
protected double lungime, latime; | |
public Dreptunghi(double lungime, double latime) { | |
super(); | |
this.lungime = lungime; | |
this.latime = latime; | |
} | |
public Dreptunghi(double x, double y, double lungime, double latime) { | |
super(x, y); | |
this.lungime = lungime; | |
this.latime = latime; | |
} | |
@Override | |
public String toString() { | |
return "Dreptunghi [lungime=" + lungime + ", latime=" + latime | |
+ ", x=" + x + ", y=" + y + "]"; | |
} | |
@Override | |
public double aria() { | |
return lungime * latime; | |
} | |
@Override | |
public double perimetrul() { | |
return 2 * (lungime + latime); | |
} | |
public double getLungime() { | |
return lungime; | |
} | |
public void setLungime(double lungime) { | |
this.lungime = lungime; | |
} | |
public double getLatime() { | |
return latime; | |
} | |
public void setLatime(double latime) { | |
this.latime = latime; | |
} | |
} |
package ro.virtualcampus.obiectgrafic; | |
public class Patrat extends Dreptunghi { | |
public Patrat(double latura) { | |
super(latura, latura); | |
} | |
public Patrat(double x, double y, double latura) { | |
super(x, y, latura, latura); | |
} | |
@Override | |
public String toString() { | |
return "Patrat [lungime=" + lungime + ", latime=" + latime | |
+ ", x=" + x + ", y=" + y + "]"; | |
} | |
} |
Instantierea de obiecte grafice de tip Cerc, Dreptunghi sau Patrat este realizata in clasa principala a aplicatiei, clasa care contine metoda main(). Metodele toString() sunt utilizate pentru a defini informatii de tip sir de caractere cu privire la o clasa. Implicit, aceste metode afiseaza numele claselor si un cod unic asociat acestora.
package ro.virtualcampus.app; | |
import ro.virtualcampus.obiectgrafic.Cerc; | |
import ro.virtualcampus.obiectgrafic.Dreptunghi; | |
import ro.virtualcampus.obiectgrafic.Patrat; | |
public class ObiecteGrafice { | |
public static void main(String args[]) { | |
Cerc cerc = new Cerc(2.3, 3.4, 1.5); | |
Dreptunghi dreptunghi = new Dreptunghi(5.2, 1.8, 3.4, 4.8); | |
Patrat patrat = new Patrat(1.3, 2.6, 4.6); | |
System.out.println(cerc); | |
System.out.println(dreptunghi); | |
System.out.println(patrat); | |
System.out.printf("Aria cerc: %.2f %n", cerc.aria()); | |
System.out.printf("Perimetru cerc: %.2f %n", cerc.perimetrul()); | |
System.out.printf("Aria dreptunghi: %.2f %n", dreptunghi.aria()); | |
System.out.printf("Perimetru dreptunghi: %.2f %n", dreptunghi.perimetrul()); | |
System.out.printf("Aria patrat: %.2f %n", patrat.aria()); | |
System.out.printf("Perimetru patrat: %.2f %n", patrat.perimetrul()); | |
} | |
} |
Cerc [raza=1.5, x=2.3, y=3.4] Dreptunghi [lungime=3.4, latime=4.8, x=5.2, y=1.8] Patrat [lungime=4.6, latime=4.6, x=1.3, y=2.6] Aria cerc: 7.07 Perimetru cerc: 9.42 Aria dreptunghi: 16.32 Perimetru dreptunghi: 16.40 Aria patrat: 21.16 Perimetru patrat: 18.40
Crearea si utilizarea interfetelor
In limbajul Java, interfetele ofera raspuns lipsei mostenirii multiple. O interfata creeaza un protocol pe care clasele trebuie sa il implementeze. Folosind interfete, poate fi precizat pentru o clasa ce sa implementeze, dar nu si cum sa faca acest lucru.
Interfetele reprezinta constructii Java similare claselor abstracte. Ele pot contine declaratii de constante si metode fara implementare. Dupa definire, o interfata poate fi implementata de un numar nedefinit de clase. De asemenea, o clasa poate implementa oricate interfete doreste.
Pentre a implementa o interfata, o clasa trebuie sa ofere implementare tuturor metodelor definite in interiorul interfetei respective. Nu prezinta importanta modul in care metodele vor fi implementate in clasa.
Definirea unei interfete se realizeaza in mod similar cu cea a unei clase, prin intermediul cuvantului cheie interface.
[modificatori] interface nume_interfata [extends lista_super_interfete] { // declaratii metode abstracte // declaratii constante }
Dupa cum se poate observa, o interfata poate mosteni una sau mai multe superinterfete.
In declaratia unei interfete poate fi utilizat doar modificatorul public. Toate atributele definite in interiorul unei interfete sunt implicit constante, chiar daca nu sunt declarate folosind modificatorii static si final. Este obligatorie initializarea acestor atribute de tip constanta. Metodele declarate intr-o interfata sunt implicit definite cu modificatorii abstract si public.
Pentru a preciza faptul ca o clasa implementeaza una sau mai multe interfete este utilizata clauza implements in declaratia clasei.
[modificatori_clasa] class nume_clasa [extends super_clasa][implements lista_interfete] { // corp clasa }
In cazul in care se doreste verificarea tipului unui obiect, poate fi utilizat operatorul instanceof. De asemenea, instanceof poate testa si daca o variabila refera un obiect a carei clasa implementeaza o interfata.
Sintaxa generala de utilizare a operatorului instanceof este urmatoarea:
referinta_obiect instanceof nume_clasa
In cele ce urmeaza consideram clasele (concrete) Persoana si Student, si interfetele IPoateEvalua si IPoateFiEvaluat. Interfata IPoateEvalua declara metoda abstracta evalueaza(), in timp ce interfata IPoateFiEvaluat introduce metoda esteEvaluat(). Deoarece clasa Persoana implementeaza interfetele, ea este obligata sa asigure implementare pentru metodele declarate in aceaste interfete.
package ro.virtualcampus.eval; | |
public interface IPoateEvalua { | |
void evalueaza(); | |
} |
Clasele concrete definite in aceasta aplicatie ofera propriile implementari ale metodelor declarate la nivelul interfetelor IPoateEvalua si IPoateFiEvaluat.
package ro.virtualcampus.person; | |
import ro.virtualcampus.eval.IPoateEvalua; | |
import ro.virtualcampus.eval.IPoateFiEvaluat; | |
public class Persoana implements IPoateEvalua, IPoateFiEvaluat { | |
protected static int nrPersoane = 0; | |
protected String nume; | |
protected int varsta; | |
public Persoana() { | |
nrPersoane++; | |
this.nume = "necunoscut"; | |
this.varsta = 0; | |
} | |
public Persoana(int varsta) { | |
this(); | |
this.varsta = varsta; | |
} | |
public Persoana(String nume, int varsta) { | |
nrPersoane++; | |
this.nume = nume; | |
this.varsta = varsta; | |
} | |
public static int getNrPersoane() { | |
return nrPersoane; | |
} | |
public void setNume(String nume) { | |
this.nume = nume; | |
} | |
public String getNume() { | |
return nume; | |
} | |
public void setVarsta(int varsta) { | |
this.varsta = varsta; | |
} | |
public int getVarsta() { | |
return varsta; | |
} | |
@Override | |
public String toString() { | |
return "Persoana [nume=" + nume + ", varsta=" + varsta + "]"; | |
} | |
@Override | |
public void esteEvaluat() { | |
System.out.println(String.format("Persoana %s este evaluata.", getNume())); | |
} | |
@Override | |
public void evalueaza() { | |
System.out.println(String.format("Persoana %s evalueaza.", getNume())); | |
} | |
} |
package ro.virtualcampus.unit; | |
public class Facultate { | |
private String nume; | |
private String adresa; | |
public Facultate(String nume, String adresa) { | |
this.nume = nume; | |
this.adresa = adresa; | |
} | |
public String getNume() { | |
return nume; | |
} | |
public void setNume(String nume) { | |
this.nume = nume; | |
} | |
public String getAdresa() { | |
return adresa; | |
} | |
public void setAdresa(String adresa) { | |
this.adresa = adresa; | |
} | |
@Override | |
public String toString() { | |
return "Facultate [nume=" + nume + ", adresa=" + adresa + "]"; | |
} | |
} |
package ro.virtualcampus.person; | |
import ro.virtualcampus.unit.Facultate; | |
public class Student extends Persoana { | |
private Facultate facultate; | |
private int anStudiu; | |
public Student(String nume, int varsta, Facultate facultate, int anStudiu) { | |
super(nume, varsta); | |
this.facultate = facultate; | |
this.anStudiu = anStudiu; | |
} | |
public Facultate getFacultate() { | |
return facultate; | |
} | |
public void setFacultate(Facultate facultate) { | |
this.facultate = facultate; | |
} | |
public int getAnStudiu() { | |
return anStudiu; | |
} | |
public void setAnStudiu(int anStudiu) { | |
this.anStudiu = anStudiu; | |
} | |
@Override | |
public String toString() { | |
return "Student [facultate=" + facultate + ", anStudiu=" + anStudiu | |
+ ", nume=" + nume + ", varsta=" + varsta + "]"; | |
} | |
@Override | |
public void esteEvaluat() { | |
System.out.println(String.format("Studentul %s este evaluat.", getNume())); | |
} | |
@Override | |
public void evalueaza() { | |
System.out.println(String.format("Studentul %s evalueaza.", getNume())); | |
} | |
} |
Clasa principala a aplicatiei Evaluari include declararea unor tablouri de tipul Student si IPoateFiEvaluat, denumite studenti, respectiv evaluati. Aceste tablouri contin elemente/obiecte de tipul Student si/sau Persoana. Dupa instantierea obiectelor este apelata metoda esteEvaluat() pentru elementele tablourilor. Parcurgerea elementelor tablourilor este realizata prin intermediul unor iteratii for.
package ro.virtualcampus.app; | |
import ro.virtualcampus.unit.Facultate; | |
import ro.virtualcampus.eval.IPoateEvalua; | |
import ro.virtualcampus.eval.IPoateFiEvaluat; | |
import ro.virtualcampus.person.Persoana; | |
import ro.virtualcampus.person.Student; | |
public class Evaluari { | |
public static void main(String[] args) { | |
Facultate etti = new Facultate("ETTI", "Vasile Parvan nr. 2"); | |
Student studenti[] = new Student[2]; | |
studenti[0] = new Student("Dorina Goia", 23, etti, 2); | |
studenti[1] = new Student("Irina Popescu", 24, etti, 3); | |
for(Student student: studenti) | |
student.esteEvaluat(); | |
IPoateFiEvaluat evaluati[] = new IPoateFiEvaluat[3]; | |
evaluati[0] = studenti[0]; | |
evaluati[1] = studenti[1]; | |
evaluati[2] = new Persoana("Virgil Ionescu", 34); | |
for(IPoateFiEvaluat evaluat: evaluati) | |
evaluat.esteEvaluat(); | |
System.out.println((evaluati[1] instanceof IPoateEvalua)? | |
String.format("%s poate evalua.", ((Student) evaluati[1]).getNume()): | |
String.format("%s nu poate evalua.", ((Student) evaluati[1]).getNume())); | |
} | |
} |
Studentul Dorina Goia este evaluat. Studentul Irina Popescu este evaluat. Studentul Dorina Goia este evaluat. Studentul Irina Popescu este evaluat. Persoana Virgil Ionescu este evaluata. Irina Popescu poate evalua.