Java: Abstraktní třídy, dědičnost a rozhraní
Z MiS
				
				
				
				
																
				
				
								
				
| Obsah | 
Dědičnost
- Zápis dědičnosti
-  Klíčové slovo extends.
- Třída může mít pouze jednu rodičovskou třídu!
- Potomek „dědí“ všechny vlastnosti předka.
-  Potomek může kdykoli nahradit předka. Takže pokud máme proměnnou datového typu Predek, můžeme do ní uložit instanci třídyPotomek. Opačně to však nejde!
- Překrývání metod
- Potomek automaticky dědí všechny metody předka. Ty může používat jako vlastní metody.
- Potomek ale může metodu nadefinovat znovu, čímž překryje (override) původní chování metody předka.
- Příklady
public class Zivocich extends Actor {
    ...
    public void act() { this.move(5); } // Živočichové se pohybují vpravo.
    ...
}
public class Moucha extends Zivocich {
    ...
    @Override
    public void act() { 
        this.turn(30); 
        // Moucha se nebude pohybovat, jen se bude točit na místě!
    }
    ...
}
- Odkaz na kód předka
-  Klíčové slovo super.
-  Můžeme odkazovat:
- Na konstruktor rodičovské třídy.
- Na překrytou metodu předka.
 
- Příklady
public class Kamion {
    int nosnost;
    ...
    public int getNosnost() { return this.nosnost; }
    ...
}
public class KamionSPrivesem extends Kamion {
    Prives prives;
    ...
    @Override
    public int getNosnost() { 
        int nosnostKamionu = super.getNosnost(); // Volání překryté metody předka.
        return nosnostKamionu+this.prives.getNosnost(); 
    }
    ...
}
public class World {
    ...
    public World(int rozmerX, int rozmerY, int dilek) { ... }
    ...
}
public class MyWorld extends World {
    ...
    public MyWorld() { 
        super(600, 400, 1); // Volání konstruktoru předka.
    }
    ...
}
Rozhraní
-  Klíčové slovo implements.
- Může mít pouze hlavičky metod a veřejné konstantní atributy.
- Implementací rozhraní garantujeme, že naše třída má určité metody.
- Zajišťujeme například to, aby objekty různých tříd šly umístit do kontejneru.
- Deklarace rozhraní
public interface Zasahnutelne {
    public void zasah(Strela s);
        // Neříkáme, jak se má objekt chovat. 
        // Jen vyžadujeme, že bude mít tuto metodu.
}
- Třída, která implementuje rozhraní
public class Prisera {
    ... 
    ... Může mít různé metody a atributy, ale musí mít metodu zasah(...)!!!
    ...
    public void zasah(Strela s) {
        // Popíšeme, jak se má reagovat na zprávu/metodu zasah(...).
        this.getWorld().removeObject(this);
    }
Abstraktní třída
-  Klíčové slovo abstract.
- Těla některých metod nejsou uvedena.
Srovnání konceptů
- Dědičnost
- Používáme tehdy, kdy potomek přebírá všechny vlastnosti předka (a případně přidává něco dalšího).
- Třída může mít jen jednoho předka.
- Rozhraní
- Pouze předepisuje, jaké metody má třída mít.
- Nemůžeme z rozhraní převzít hotový kód.
-  Nelze vytvořit instanci rozhraní (nelze volat new Rozhrani()).
- Můžeme implementovat kolik rozhraní chceme.
- Je užitečné, když každá třída má na společnou zprávu reagovat jinak.
- Abstraktní třída
- Je jakýmsi mezistupněm, kdy přebíráme kód jen některých metod.
- Nelze vytvářet instance abstraktní třídy.
  Odkaz na předka — super 
- Jsou situace, kdy potřebujeme změnit chování některé metody předka v potomkovi. Mluvíme o překrývání metod.
-  Pokud potřebujeme v potomkovi přesto použít metodu předka, použijeme k tomu klíčové slovo super.
-  Klíčovým slovem superlze také zavolat konstruktor předka.
Přetypování
- Potomek může vždy zastoupit předka. Do proměnné datového typu předka tedy můžeme uložit instanci třídy potomka.
- Jsou ale situace, kdy potřebujeme k takto uloženému potomkovi znovu přistupovat jako k potomkovi včetně všech jeho metod a atributů.
- V tom případě musíme použít přetypování.
- Přetypování zapíšeme tak, že do závorky před výraz, který vrací takto uloženého potomka, zapíšeme název třídy předka.
- Příklady přetypování
- Greenfoot a detekce kolize s konkrétním typem aktéra
Prekazka prekazka = (Prekazka) this.getOneIntersectingObject(Prekazka.class);
if (prekazka != null) {
    int prekazka.getPruhlednost();
    ...
}
- GUI pomocí knihovny Swing — zjištění zdroje události
public void actionPerformed(ActionEvent event) {
    Button zdroj = (Button) event.getSource();
    zdroj.getTitle();
    ...
}
Pozor, musíme si být stoprocentně jisti, že objekt, který je uložen v proměnné datového typu 
Predek je ve skutečnosti opravdu datového typu Potomek. Pokud by nebyl, běh programu by skončil výjimečný stavem a aplikace by havarovala.