Dědičnost

Abstraktní třídy a metody

Abstraktní třída je taková třída, jejíž instance nelze přímo vytvářet. K čemu je tedy užitečná? Slouží jako společný předek, na základě kterého vytváříme odvozené třídy. Přitom se využívá tzv. dědičnost - odvozená třída (potomek) dědí členské proměnné a metody po své rodičovské třídě. Ukažme si, jak může, například, vypadat společný předek všech geometrických útvarů - abstraktní třída Utvar:

abstract class Utvar {
  protected String barva;
  public Utvar() {
  }
  public void setBarva(String barva) {
    this.barva = barva;
  }
  public String getBarva() {
    return barva;
  }
  abstract public double obsah();
}

Instanci třídy Utvar není možné vytvořit, je to abstraktní třída (její definice začíná klíčovým slovem abstract). Tato třída obsahuje jednu členskou proměnnou barva a dvě metody pro nastavení a zjištění barvy útvaru. Navíc třída obsahuje metodu obsah(), u které chybí tělo metody. Jedná se o tzv. abstraktní metodu (klíčové slovo abstract), jejíž smysl je takový, že každý potomek třídy Utvar ji musí implementovat, tj. v definici každého potomka musí být tato třída uvedena i včetně svého těla.

Nyní se podívejte, jak může vypadat definice potomka abstraktní třídy Utvar. Bude se jednat o třídu Bod (bod je z hlediska geometrického také útvar, i když velmi jednoduchý).

public class Bod extends Utvar {
  private int x, y;
  public Bod() {
    x = 0;
    y = 0;
  }
  public double obsah() {
    return 0;
  }
  public void info() {
    System.out.println("Bod [" + x + "," + y + "]");
  }
}

Všimněte si klíčového slova extends hned za názvem třídy. Tímto způsobem se v Javě vyjadřuje fakt, že třída Bod je potomkem třídy Utvar. Co to v praxi znamená? Třída Bod zdědí všechny členské proměnné i metody rodičovské třídy Utvar. Aniž bychom tedy v definici třídy Bod uvedli proměnnou barva, bude ji tato třída mít, protože je zdědila od třídy Utvar. Podobně je to s metodami setBarva() a getBarva(). Trochu jinak je to s metodou obsah(), ta byla ve třídě Utvar definována jako abstraktní a proto musí být ve třídě bod uvedena i včetně svého těla. To je správný přístup, neboť obsah každého útvaru se počítá trochu jinak, například bod má vždy nulový obsah. Do definice třídy Bod jsme přidali ještě metodu info(), ta slouží pro výpis informací o daném útvaru, v našem případě vypíše pouze souřadnice bodu.

Nyní se podívejte, jak může vypadat definice jiného potomka abstraktní třídy Utvar. Bude se jednat o třídu Kruh (bod je z hlediska geometrického také útvar, i když velmi jednoduchý).

public class Kruznice extends Utvar {
  private int x, y, r;
  public Kruznice() {
    x = 0;
    y = 0;
    r = 1;
  }
  public double obsah() {
    return Math.PI*r*r;
  }
  public void info() {
    System.out.println("Kruznice [" + x + "," + y + "], r=" + r);
  }
}

Výše uvedené třídy otestujeme pomocí třídy Test. Jednotlivé třídy je vhodné umístit samostatně do souborů s názvy totožnými s názvy tříd (třídy mohou být i v jednom souboru, ale při větším počtu tříd je to nepřehledné).

class Test {
    public static void main(String[] args) {
    Bod A = new Bod();
    A.info();
    System.out.println("Obsah: " + A.obsah());
    Kruznice k = new Kruznice();
    k.info(); 
    System.out.println("Obsah: " + k.obsah());
    }
}

Cvičení:

  1. Doplňte do tříd Utvar, Bod a Kruznice jednoparametrické konstruktory, které budou umožňovat určit barvu utvaru přímo při jeho vytvoření.
  2. Doplňte do tříd Bod a Kružnice víceparametrické konstruktory, které budou umožňovat určit barvu a souřadnice útvaru a v případě kružnice i poloměr.
  3. Vytvořte další třídu Ctverec, která bude potomkem třídy Utvar a bude fungovat podobně, jako třídy Bod a Kruznice.