Kihagyás

Öröklődés példa - Torta

Öröklődés

Tekintsük az alábbi példát:

public class Torta {
    protected int szelet;
    private String iz;

    public String getIz() {
        return iz;
    }

    public void setIz(String iz) {
        this.iz = iz;
    }

    public Torta(int szelet, String iz) {
        this.szelet = szelet;
        this.iz = iz;
    }

    public void info() {
        System.out.println("Ez a torta " + this.iz + " ízű, és "
                + this.szelet + " szeletes.");
    }
}

Extends, super

Ez egy általános torta osztály, tudjuk, hogy egy torta milyen ízű és hány szeletből áll. Tortát bármilyen alkalomra vásárolhatunk, azonban lehetnek speciális alkalmak, amelyek esetében szeretnénk használni a már megírt Torta osztályunkat, de szeretnénk új, speciálisabb adatokat, metódusokat létrehozni a tortáinknak. Ilyen lehet például egy SzulinapiTorta osztály, amely torta, de szeretnénk egy új adatot is tárolni, mégpedig a rajta lévő gyertyák darabszámát.

extends - ezzel a kulcsszóval érhetjük el az öröklődést, az osztály deklarációjában, az osztály neve után kell írnunk, majd az extends kulcsszó után az ősosztály nevét írjuk.

super - a gyerekosztályból hivatkozhatunk a szülőre, annak adattagjaira (amiket látunk) és metódusaira is, ezeket super.szuloMetodusanakNeve()-szerű parancsokkal érhetjük el.

public class SzulinapiTorta extends Torta {
    private int gyertyakSzama;

    public SzulinapiTorta(int szelet, String iz, int gyertyakSzama) {
        super(szelet, iz);
        this.gyertyakSzama = gyertyakSzama;
    }

    public void kivansagotTeljesit() {
        System.out.println("Kívánságod teljesült!");
    }

    public void info() {
        System.out.println("Ez a szülinapi torta " + this.getIz() + " ízű, és "
                + this.szelet + " szeletes." + this.gyertyakSzama
                + " db gyertya van rajta");
    }

}

A szülő konstruktora pedig egyszerűen a super kulcsszó metódusként való használatával érhető el, például:

super(szelet, iz);

Ha az ősosztály paraméter nélküli konstruktorát szeretnénk meghívni, akkor a super(); hívás a gyermekosztály konstruktorában elhagyható. Ha nem a default konstruktorát használjuk az ősosztálynak, akkor viszont kötelező a super(arg1,arg2...argn); meghívása a gyerekosztály konstruktorában!

A gyerekosztályban láthatjuk, hogy az ősből örökölt info() metódust felüldefiniáltuk (override), annak egy speciálisabb működést adtunk.

Polimorfizmus - Többalakúság

A gyerekosztály egy példánya kezelhető a szülő egy példányaként is, egy SzülinapiTorta objektumot tárolhatunk Torta példányként is (azaz egy Torta típusú referenciában), sőt akár egy ős típusú tömbben eltárolhatjuk az ős- és gyerektípusokat vegyesen. Azonban, ha ős típusként tárolunk egy gyerek típusú objektumot, akkor a gyerek típusú objektum saját osztályában definiált metódusait nem látjuk. Például:

public class TortaMain {
    public static void main(String[] args) {
        Torta csokiTorta = new SzulinapiTorta(15, "csoki", 9);
        csokiTorta.kivansagotTeljesit();    // Ez nem fog működni
    }
}

A fenti kódrészlet nem működik, mert az átlagos Torta nem tud kívánságot teljesíteni. Mivel egy Torta referenciában tároljuk a SzülinapiTorta objektumot, így csak a Tortában definiált metódusokat használhatjuk! Ennek kiküszöbölésére később látni fogunk egy módszert.

Ugyanígy nem lehetne a gyertyák számát lekérni vagy módosítani sem (még akkor sem, ha public láthatóságú lenne ez az adattag), mert az érintett Torta nem biztos, hogy rendelkezik ilyen adattaggal.

Torta[] cukraszda = new Torta[3];
cukraszda[0] = new Torta(20, "csokis-meggyes");
cukraszda[1] = new Torta(12, "epres");
cukraszda[2] = new SzulinapiTorta(12, "karamell", 12);

Fordításkor még nem tudjuk, hogy a Torta tömbben milyen típusú objektumok lesznek: Torta objektumok, vagy pedig SzulinapiTorta objektumok, esetleg vegyesen, hiszen megtehetjük, hogy egy tömbbe gyerek típusokat teszünk. Viszont, ha meghívjuk mindegyik elem info() metódusát, azt látjuk, hogy a sima torták esetében a Torta osztályban definiált metódus fut le, míg a születésnapi torta esetében a SzulinapiTorta osztályban definiált info() metódus hívódik meg. Ennek oka pedig a kései kötés (late binding). A kései és korai kötésről bővebben itt és itt olvashatsz.

for (int i = 0; i < cukraszda.length; i++) {
    cukraszda[i].info();
}

Ennek kimenete:

Ez a torta csokis-meggyes ízű, és 20 szeletes.
Ez a torta epres ízű, és 12 szeletes.
Ez a szülinapi torta karamell ízű, és 12 szeletes. 12 db gyertya van rajta

Ahogy említettük, a gyerek típus kezelhető ősként, viszont ez fordítva nem működik! SzülinapiTorta tömbbe nem tehetünk ős típusú, azaz sima Torta objektumokat.


Utolsó frissítés: 2024-04-11 07:54:27