Különféle italok

Ok, eddig jó, de hogy lesznek különféle italok? Az italok mind az Innivalo osztályból valók, de valahogy más-más alkohol tartalommal kellene rendelkeznie.

Az lenne a jó, ha megadhatnánk egy Innivalo példánynak, hogy most akkor pontosan mennyi alkoholt is tartalmaz!

Erre való a konstruktor. A konstruktor egy speciális metódus, ami akkor hívódik meg, amikor egy objektum-példányt létrehoznak. Na ez most kínai, de valóságban egyszerű a dolog:

public class Innivalo {
    double felszolgaltMeret=5; // dl
    double alkoholTartalomSzazalek=4; // %      

    // ez itt a konstruktor, ugyanaz a neve mint az osztalynak,
    // es nincs visszateresi erteke 
    Innivalo(double felszolgaltMeret,double alkoholTartalomSzazalek) {
        this.felszolgaltMeret=felszolgaltMeret;
        this.alkoholTartalomSzazalek=alkoholTartalomSzazalek;
    }
}

Semmi extra, igaz? Csak mi az a this kulcsszó? A this azt jelenti, hogy "ez", vagy "ezé". A konstruktor paraméterének neve felszolgaltMeret, de ugyanilyen néven van egy változó az osztályban is.

Azt szeretnénk, hogy az osztályban lévő felszolgaltMeret értékét állítsuk be, mégpedig pont arra, amit a paraméterben kapunk. Akkor:

felszolgaltMeret=felszolgaltMeret;

Oookés, de akkor melyik felszolgaltMeret melyik? Melyik az, amit az osztály elején deklaráltunk, és melyik a paramáter? A this ezen segít, a this segítségével meg lehet jelölni, hogy "az a felszolgaltMeret amit ebben az osztályban adtunk meg", na az legyen akkora, mit a paraméter.


Aztán amikor létrehozzuk az innivalót, megmondjuk, hogy akkor mennyi is legyen ez a két érték:

public class Kocsma {

    public static void main(String[] args) {
        Ember jack=new Ember();
        Ember jane=new Ember();

        jack.igyal(new Innivalo(5,4)); // 5 deci, 4% - ez sor
        jack.igyal(new Innivalo(0.5,40)); // 0.5 deci, 40% - palinka
        jack.igyal(new Innivalo(10,12)); // egy teljes liter bor
    }
}

Öröklés

Jó jó, de miért nem írhatnánk azt, hogy jack.igyal(new Sor()) meg jack.igyal(new Palinka()) ? Vajon elég lenne egyszerűen csinálni egy Sor meg egy Palinka osztályt?

Nos, nem, nem lenne az úgy jó. Merthogy, az igyal metódusból akkor kellene olyat csinálni, ami Sor-t fogad. Meg olyat is, ami Palinkat. Meg 20 féle másikat. De... de a valóságban sem 20 féleképpen kezeli Jack az italokat, nem?

Voltaképpen minden italt egyformán meg tud inni Jack. Az italok közös tulajdonsága, hogy megiható, meg hogy van bennük valamennyi alkohol. Az italok különböző tulajdonsága hogy mennyi alkohol van benne.

Az OOP egyik legjobb része az öröklés. Ez azt jelenti, hogy csinálhatunk egy osztályt, ami "pont olyan mint az őse", csak egy-két dologban picit másként működik. Viszont, azt amit az ősében már leprogramoztunk, azt nem kell leírnunk újra.

A sör, bor, pálinka mind innivaló

Tehát egy Sör az egy Innivalo, ami létrehozáskor 5 deci és 4%-nyi alkoholtartalommal bír:

public class Sor extends Innivalo {
    Sor() {
        super(5,4); // 5 dl, 4%
    }
}

Mi ebben az új?

Van egy extends kulcsszó, ami azt jelenti, hogy a Sor osztály kibővíti az Innivaló osztályt (azaz mindent megörököl belőle, lesz neki felszolgaltMeret, meg alkoholSzazalek tulajdonsága).

Csináltunk neki egy Sor() konstruktort, immár paraméterek nélkül. Jack sosem mondja, hogy "kérek egy 5 decis pohárban 4%-nyi alkoholos italt", hanem csak annyit mond: "egy sört!".

Persze ettől még az Innivalót létre kell hozni a megfelelő paraméterekkel. A super kulcsszó azt jelenti, hogy a "felmenőm", az "ősöm" és jelen esetben meghívja az Innivalo osztály konstruktorát a megfelelő paraméterekkel.

Az eredmény? Olvasható kód, és immár Jack sört iszik, nem pedig "5 decis pohárban 4%-nyi alkoholos italt". Szóval olvasható kód:

jack.igyal(new Sor());

Add hozzá a Bor és a Pálinka osztályt is:

public class Bor extends Innivalo {
    Bor() {
        super(1,12); // 1 dl, 12%
    }
}
public class Palinka extends Innivalo {
    Palinka() {
        super(0.5,40); // 0.5 dl, 40%
    }
}

Az örökléssel leszármazott osztályok mindenben azonosak az ős osztállyal, csak még valami további dolgot is tudnak. Ezért bárhova ahova az ős osztályt használhatjuk paraméternek, bármely leszármazott osztályt is használhatunk.

Na mégegyszer: a Sor az Innivalo, a Bor az Innivalo, a Palinka az Innivalo. Mivel egy Ember bármi Innivalo-t meg tud inni, ezért bármi Innivalo-leszármazottat is meg tud inni, így Sor-t, Bor-t, Palinka-t.

Pont mint a valóságban! Ha tudunk innivalót inni, akkor bármilyen innivaló-féleséget megihatunk!

No és itassuk meg Jacket:

public class Kocsma {

    public static void main(String[] args) {
        Ember jack=new Ember();
        Ember jane=new Ember();

        jack.igyal(new Bor());
        jack.igyal(new Bor());
        jack.igyal(new Palinka()); 
        jack.igyal(new Bor());
        jack.igyal(new Sor());
        jack.igyal(new Palinka()); 
        jack.igyal(new Sor());
        jack.igyal(new Palinka()); 
        jack.igyal(new Sor());
        jack.igyal(new Palinka()); 
        jack.igyal(new Sor());
        jack.igyal(new Palinka()); 
        jack.igyal(new Sor());
        jack.igyal(new Palinka()); 
        jack.igyal(new Sor());
    }
}

Feladat: Vajon ha csak pálinkát iszik, mennyit tud Jack meginni kidőlés nélkül?

Feladat: Vajon bort vagy pálinkát ihat több pohárral?