Relația de tip is-a

Uneori, ca programatori, suntem puși în situația de a avea nevoie de clase care au unele atribute și metode similare, dar care au și unele atribute și metode distincte.

Să presupunem că trebuie să realizăm o aplicație care să stocheze diferite localități din România. Vom stoca localități de toate tipurile, toate dimensiunile, din toate județele.

La o primă vedere, putem crea clasa Localitate care să aibă următoarele atribute:

String denumire;
int numărDeLocuitori;
String județ;
String tipulLocalitatii;
String adresaPrefectura;
String adresaPrimarie;
String adresaSpital;

Ne dăm seama imediat că nu toate localitățile au primărie, și nici prefectură și nici spital și că trebuie să creăm clase separate. Prefectură au doar reședințele de județ, Primărie nu au unele sate, ci doar satele reședință de comună, iar comunele nu au spitale. Totuși, există și atribute pe care le au toate localitățile: denumire, număr de locuitori, județ etc.

Soluția: facem o clasă generică Localitate și mai multe subclase care să moștenească această clasă, dar care să aibă și unele atribute distincte. Renunțăm la atributul tipulLocalitatii.

public class Localitate {
    private String denumire;
    private int numărDeLocuitori;
    private String județ;

    public Localitate(String denumire, int numarDeLocuitori, String judet) {
        this.denumire = denumire;
        this.numarDeLocuitori = numarDeLocuitori;
        this.judet = judet;
    }

    // getteri, setteri
}
Apoi creăm clasele ResedintaJudet, Oras, SatResedintaComuna, Sat care extind clasa Localitate:
public class ResedintaJudet extends Localitate {
    private String adresaPrefectura;
    private String adresaPrimarie;
    private String adresaSpital;

    public ResedintaJudet(String denumire, int numarDeLocuitori, String judet,
                String prefectura, String primarie, String spital){
        super(denumire, numarDeLocuitori, judet);
        this.adresaPrefectura = prefectura;	
        this.adresaPrimarie = primarie;
        this.adresaSpital = spital;
    }

    // getteri, setteri pentru cele 3 atribute specifice clasei
}

public class Oras extends Localitate {
    private String adresaPrimarie;
    private String adresaSpital;

    public Oras (String denumire, int numarDeLocuitori, String judet,
                String primarie, String spital) {
        super(denumire, numarDeLocuitori, judet);		
        this.adresaPrimarie = primarie;
        this.adresaSpital = spital;
    }

	// getteri, setteri pentru cele 2 atribute specifice clasei
}

public class SatResedintaComuna extends Localitate {
    private String adresaPrimarie;

    public SatResedintaComuna(String denumire, int numarDeLocuitori, String judet,
            String primarie){
        super(denumire, numarDeLocuitori, judet);
        this.adresaPrimarie = primarie;		
    }

    // getteri, setteri pentru adresaPrimarie
}

public class Sat extends Localitate {
    public Sat (String denumire, int numarDeLocuitori, String judet) {
        super(denumire, numarDeLocuitori, judet);			
    }
}

Deși clasa ResedintaJudet pare să aibă doar 3 atribute, în realitate are 6, pentru că le moștenește și pe cele ale clasei Localitate. De asemenea, moștenește și toate metodele superclasei, inclusiv getteri și setteri.

Atentie: Dacă cele 3 atribute ale clasei Localitate sunt private tot le moșteneşte, dar nu le vom putea folosi direct, ci prin intermediul getterilor (=accesorilor) și setterilor (=mutatorilor) pe care îi moștenește.

Oras oras = new Oras (”Galati”, 300000, “Galati”, “...”, “.....”);
oras.getDenumire(); // mosteneste aceasta metoda de la clasa mama. O putem folosi direct.

Constructorul ResedintaJudet va contine toate cele 6 argumente. Prima linie în constructorul unei subclase care moștenește o altă clasă, trebuie să fie trimiterea la constructorul superclasei utilizând instructiuneasuper();.

  • super() = apelarea constructorului superclasei

Dacă noi nu scriem super();, acest lucru îl va facem automat compilatorul care va insera pe prima linie în codul compilat, comanda super();. În cazul nostru, noi vom apela constructorul superclasei care are cele 3 argumente:

public Localitate(String denumire, int numarDeLocuitori, String judet)

folosind comanda :

super(denumire, numarDeLocuitori, judet);

Atenție, dacă superclasa nu are constructorul default (fără argumente) ci un alt constructor, iar noi nu vom menționa keywordul super, vom avea o eroarea de compilare, întrucât compilatorul va introduce keywordul super() automat care va apela un constructor care nu există.

Dacă există deja un constructor scris de noi cu argumente, compilatorul nu mai introduce constructorul default.

Ca o dovadă că se moștenesc și atributele private, apelaţi în metoda main():

oras.setDenumire(”Braila”);
Faceți o metodă toString() în clasa mamă (Localitate) și apoi, în metoda main() scrieți:
System.out.println(oras);

Ce obținem?

Localitate [denumire=Braila, ….]

Deși moștenește atributele private, nu vom putea, totuși, scrie direct într-o metodă a clasei Oras următorul cod: this.denumire = ”Iasi”;. Dar vom putea folosi getterul, care se moşteneşte de asemenea, si care are access specifier public, astfel: this.setDenumire(“Iasi”);, unde this se referă la instanța (obiectul) cu care lucrăm, care are atribute și metode specifice.

You could leave a comment if you were logged in.