Cvičenie 10 – Dedičnosť a polymorfizmus

Cieľom cvičení je pozrieť sa na praktické využitie dedičnosti a polymorfizmu.

Tvar

  • Vytvorte triedu Tvar, ktorá bude uchovávať súradnice x a y stredu nejakého geometrického tvaru a jeho farbu.
  • Vytvorte potomkov triedy Tvar (k všetkým si dodajte potrebné inštančné premenné):
    • Kruh
    • Obdlzdnik
  • Umožnite, aby sa každý tvar vedel vykresliť na WinPane z JPaz2 frameworku:
  • kreslenie tvaru prebieha cez zavolanie metódy vykresliSa(Pane plocha)
  • metóda vykresliSa nech je definovaná v triede Tvar (pri jej volaní nad touto triedou, nech sa vypíše do System.err chybová hláška) a v triedach Kruh a Obdlznik nech je táto metóda vhodne prekrytá.

1
public void vykresliSa(Pane plocha)
  • Vyskúšajte metódu vykresliSa:

1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) {
  WinPane plocha = new WinPane();
  Tvar t;
  if (Math.random() < 0.5) {
    t = new Kruh(...);
  } else {
    t = new Obdlznik(...);
  }

  t.vykresliSa(plocha);
}
  • Čo sa stane, ak by trieda Tvar nemala metódu vykresliSa, ale mali by ju len triedy Kruh a Obdlznik?
  • Kde v tejto metóde main sa nachádza polymorfizmus?
  • Vytvorte metódu (v triede Tvar a prekrytú v oddedených triedach), ktorá vráti, či bod so súradnicami [x, y] je vnútorným bodom daného tvaru:

1
public boolean jeVnutornyBod(double x, double y)

Zoznam tvarov

  • Vytvorte triedu ZoznamTvarov ktorá bude obsahovať všetky tvary v poli typu Tvar[].
    • vytvorte vhodné metódy na pridávanie nových tvarov do zoznamu tvarov
    • vytvorte metódu nakresliVsetky(Pane plocha), ktorá vykreslí všetky tvary do zadanej kresliacej plochy Pane
    • vytvorte vlastnú triedu rozširujúcu kresliacu plochu WinPane, ktorej objekty budú v sebe udržiavať vlastný ZoznamTvarov
    • vytvorte metódu posun(double dx, double dy), ktorá posunie všetky tvary v smere zadaného vektora [dx, dy]
    • vytvorte metódu bodTvaru(double x, double y), ktorá vráti referenciu na objekt triedy Tvar, ktorého vnútorným bodom je bod so súradnicami [x, y], resp. null, ak takého objektu niet.
    • vytvorte metódu na odstránenie tvaru, zo zoznamu tvarov
    • vytvorte metódu posunSmerom(double uhol, double vzdialenost), ktorá posunie všetky tvary daným smerom o danú vzdialenosť

Štruktúra triedy ZoznamTvarov:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import sk.upjs.jpaz2.Pane;

public class ZoznamTvarov {
    //???

    public void pridajTvar(Tvar t) {
        //???
    }

    public void nakresliVsetky(Pane plocha) {
        //???
    }

    public void posun(double dx, double dy) {
        //???
    }

    public Tvar bodTvaru(double x, double y) {
        return null;
    }

    public void odstranTvar(Tvar t) {
        //???
    }
}

Návrh triedy rozširujúcej WinPane na experimentovanie s tvarmi:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import java.awt.event.MouseEvent;

import sk.upjs.jpaz2.WinPane;

public class PlochaTvarov extends WinPane {

    private ZoznamTvarov tvary;

    private double dragX;
    private double dragY;
    private boolean tahanie = false;

    public PlochaTvarov() {
        this.tvary = new ZoznamTvarov();
    }

    @Override
    protected void onMouseClicked(int x, int y, MouseEvent detail) {
        if (detail.getButton() == MouseEvent.BUTTON1) {
            if (detail.isAltDown()) {
                this.tvary.pridajTvar(new Kruh(???));
            } else {
                this.tvary.pridajTvar(new Obdlznik(???));
            }
        }

        if (detail.getButton() == MouseEvent.BUTTON3) {
            Tvar naOdstranenie = this.tvary.bodTvaru(x, y);
            if (naOdstranenie != null) {
                this.tvary.odstranTvar(naOdstranenie);
            }
        }

        this.clear();
        this.tvary.nakresliVsetky(this);
    }


    @Override
    protected void onMousePressed(int x, int y, MouseEvent detail) {
        if (detail.getButton() == MouseEvent.BUTTON1) {
            this.tahanie = true;
            this.dragX = x;
            this.dragY = y;
        }
    }

    @Override
    protected void onMouseDragged(int x, int y, MouseEvent detail) {
        if (this.tahanie) {
            tvary.posun(x - this.dragX, y - this.dragY);
            this.dragX = x;
            this.dragY = y;
            this.clear();
            this.tvary.nakresliVsetky(this);
        }
    }

    @Override
    protected void onMouseReleased(int x, int y, MouseEvent detail) {
        if (detail.getButton() == MouseEvent.BUTTON1) {
            this.tahanie = false;
        }
    }
}

Tvary v súroborch

  • vymyslite spôsob, akým by ste vedeli všetky tvary uchovávať v textovom súbore
    • vytvorte metódu na uloženie tvarov do textového súboru
    • vytvorte metódu na vytvorenie zoznamu tvarov čítaním tohto textového súboru

Obsahy tvarov

  • Vytvorte vo vhodných triedach metódu obsah(), ktorá vráti obsah daného útvaru
  • Upravte triedu PlochaTvarov tak, aby po vhodnom kliknutí na tvar sa v konzole vypísal jeho obsah.

Ďalšie tvary (Tvary++)

  • Vytvorte ďalšie triedy a zvoľte im vhodných rodičov
    • Sestuholnik
    • Hviezda
  • pre fajnšmekrov: Vytvorte triedu Krivka – potomka triedy Tvar – vytvorenú myšacími udalosťami

Polymorfizmus

  • Nájdite a diskutujte o rôznych príkladoch, kde by išlo využiť dedičnosť a polymorfizmus (jednotlivé príklady môžete skúsiť aj implementovať).

Konštruktory

  • Rozdiskutujte a na príkladoch vysvetlite pravidlá:
    • Každá trieda v Jave musí mať konštruktor. Ak programátor nenapíše žiaden konštruktor, Java vytvorí implicitný konštruktor.
    • Prvý príkaz každého konštruktora je volanie konštruktora rodičovskej triedy alebo iného konštruktora danej triedy. Ak to tak nie je, Java pridá pred prvý riadok volanie bezparametrového konštruktora rodičovskej triedy (super();).

Výstava psov

Vytvoríme program, ktorý pomôže organizátorom výstavy psov. O každom súťažiacom vieme meno psa, meno majiteľa, rasu psa, vek psa a hodnotenie psa od piatich rozhodcov.

Zoznam súťažiacich je v textovom súbore vystava.txt


1
2
3
4
5
6
7
8
9
10
11
12
Fik Alfonz Morlok beagle 5 4.5 5.0 3.2 5.2 3.9
Dunco Leo Huba doberman 7 2.2 1.6 3.0 2.7 2.3
Rexo Maria Biela doberman 2 4.6 3.9 5.5 5.9 4.0
Aaron Hana Anzurova Čivava 12 4.5 6.0 5.0 5.5 5.0
Nero Viliam Janos doga 9 3.0 3.0 4.2 3.7 2.9
Viki Augustin Hrbolek beagle 5 1.3 1.6 2.0 1.7 1.5
Punto Alena Strelena Čivava 5 5.1 4.8 4.2 4.6 4.8
Drobec Robert Ficko doga 4 6.0 5.7 2.7 5.6 5.1
Dany Farantisek Hrable doberman 6 4.0 3.9 3.2 4.2 3.6
Cezar Zoltan Horvath beagle 7 6.0 5.2 5.1 5.8 4.9
Strapacik Jan Pan doberman 7 4.7 4.2 3.9 4.6 5.0
Falco Peter Peniaz doberman 9 1.0 1.0 3.1 2.2 1.6
  • Vytvorte triedu Pes, kde sú uložené všetky uvedené informácie o jednom súťažiacom. Trieda ZoznamPsov, ktorá bude spravovať zoznam objektov triedy Pes.
  • V triede Pes vytvorte metódu na výpis všetkých známych informácií o danom psovi.
  • Naplňte zoznam psov cez načítanie údajov z textového súboru
  • Vytvorte metódu na výpis informácií o všetkých súťažiacich psoch, využite metódu z druhého bodu.
  • Vytvorte metódu, ktorá vypočíta a vhodne uloží celkové hodnotenie psa na základe ohodnotení od rozhodcov.
  • Vytvorte metódu vypisVitaza(), ktorá vypíše informácie o víťaznom psovi, teda o psovi, ktorý má najvyššie priemerné ohodnotenie od rozhodcov.

O kuchárskej knihe a chladničke

Chcete implementovať kuchársku knižku. Každý recept má najprv zoznam surovina-mnozstvo a potom text s „algoritmom“ teda poradím ako jednotlivé suroviny použiť.

  • chcete vedieť vypísať všetky recepty
  • chcete vypísať recept podľa názvu jedla
  • pre daný obsah chladničky a špajzy (zoznam surovina-množstvo) chcete vypísať tie recepty, ktoré sa dajú navariť

Aké triedy je treba vytvoriť na riešenie tejto úlohy? Čo by mali jednotlivé triedy uchovávať a akými metódami by mali disponovať?