Vloženo:

Úkol 05 - Vlastnosti

Úkolem je naprogramovat třídu na práci s dnem, měsícem a rokem. Podobná třída už existuje v Javě, ale my si ji ze cvičných důvodů napíšeme znovu.

Část 1

Založte nový projekt, stejně jako v hodině: Create new project -> User Defined Template -> Java Console App. Nazvěte ho Datum, uložte do JAVATRAINING/Projects/Java-1/Lekce06/Datum a base package zvolte cz.czechitas.kalendar.

Vytvořte třídu Datum tak, aby měla následující složky:

Datum
  |
  +-- int rok;
  |
  +-- int mesic;
  |
  +-- int den;
  |
  +-- public String toString()

Naprogramujte toString() tak, aby takováto metoda main(...) vypisovala následující výstup:

public static void main(String[] args) {
    Datum dnesek = new Datum();
    dnesek.rok = 2018;
    dnesek.mesic = 11;
    dnesek.den = 9;
    System.out.println(dnesek);

    Datum letosniVanoce = new Datum();
    letosniVanoce.rok = 2018;
    letosniVanoce.mesic = 12;
    letosniVanoce.den = 24;
    System.out.println(letosniVanoce);

    Datum letosniSilvestr = new Datum();
    letosniSilvestr.rok = 2018;
    letosniSilvestr.mesic = 12;
    letosniSilvestr.den = 31;
    System.out.println(letosniSilvestr);

    if (letosniVanoce.mesic == letosniSilvestr.mesic) {
        System.out.println("Vanoce a Silvestr jsou ve stejnem mesici.");
    } else {
        System.out.println("Vanoce a Silvestr NEJSOU ve stejnem mesici.");
    }

    System.out.println();

    Datum nesmyslnyMesic = new Datum();
    nesmyslnyMesic.rok = 2020;
    nesmyslnyMesic.mesic = 13;
    nesmyslnyMesic.den = 11;
    System.out.println(nesmyslnyMesic);

    Datum nesmyslnyMesic2 = new Datum();
    nesmyslnyMesic2.rok = 2021;
    nesmyslnyMesic2.mesic = -1;
    nesmyslnyMesic2.den = 5;
    System.out.println(nesmyslnyMesic2);

    Datum nesmyslnyDen = new Datum();
    nesmyslnyDen.rok = 2022;
    nesmyslnyDen.mesic = 12;
    nesmyslnyDen.den = 40;
    System.out.println(nesmyslnyDen);

    Datum nesmyslnyDen2 = new Datum();
    nesmyslnyDen2.rok = 2023;
    nesmyslnyDen2.mesic = 3;
    nesmyslnyDen2.den = -2;
    System.out.println(nesmyslnyDen2);
}

Výstup:

Datum 24. 12. 2018
Datum 31. 12. 2018
Vanoce a Silvestr jsou ve stejnem mesici.

Datum 11. 13. 2020
Datum 5. -1. 2021
Datum 40. 12. 2022
Datum -2. 3. 2023

Část 2

Nelíbí se mi, že se do objektu typu Datum dá vložit neplatná hodnota dne a měsíce. Řekněme, že platné hodnoty jsou:

Přeprogramujte tedy třídu Datum tak, aby všechny proměnné byly private a následně doprogramujte metody podle seznamu:

Datum
  |
  +-- private int rok;
  |
  +-- private int mesic;
  |
  +-- private int den;
  |
  +-- public String toString()
  |
  +-- public void setRok(int novaHodnota)
  |
  +-- public void setMesic(int novaHodnota)
  |
  +-- public void setDen(int novaHodnota)
  |
  +-- public int getRok()
  |
  +-- public int getMesic()
  |
  +-- public int getDen()
  |
  +-- public String getNazevMesice()

Pozor, settery musejí akceptovat jen platné hodnoty. Pokud se pokusíme vložit neplatnou hodnotu, setter novou hodnotu neakceptuje a vypíše chybovou hlášku pomocí System.out.println(...).

Pokud by metoda main(...) vypadala takto, mohl by výstup být následující:

public static void main(String[] args) {
    Datum dnesek = new Datum();
    dnesek.setRok(2018);
    dnesek.setMesic(11);
    dnesek.setDen(9);
    System.out.println(dnesek);
    System.out.println("Mesic: " + dnesek.getNazevMesice());

    System.out.println();

    Datum letosniVanoce = new Datum();
    letosniVanoce.setRok(2018);
    letosniVanoce.setMesic(12);
    letosniVanoce.setDen(24);
    System.out.println(letosniVanoce);

    Datum letosniSilvestr = new Datum();
    letosniSilvestr.setRok(2018);
    letosniSilvestr.setMesic(12);
    letosniSilvestr.setDen(31);
    System.out.println(letosniSilvestr);

    if (letosniVanoce.getMesic() == letosniSilvestr.getMesic()) {
        System.out.println("Vanoce a Silvestr jsou ve stejnem mesici.");
    } else {
        System.out.println("Vanoce a Silvestr NEJSOU ve stejnem mesici.");
    }

    System.out.println();

    Datum nesmyslnyMesic = new Datum();
    nesmyslnyMesic.setRok(2020);
    nesmyslnyMesic.setMesic(13);
    nesmyslnyMesic.setDen(11);
    System.out.println(nesmyslnyMesic);

    Datum nesmyslnyMesic2 = new Datum();
    nesmyslnyMesic2.setRok(2021);
    nesmyslnyMesic2.setMesic(-1);
    nesmyslnyMesic2.setDen(5);
    System.out.println(nesmyslnyMesic2);

    Datum nesmyslnyDen = new Datum();
    nesmyslnyDen.setRok(2022);
    nesmyslnyDen.setMesic(12);
    nesmyslnyDen.setDen(40);
    System.out.println(nesmyslnyDen);

    Datum nesmyslnyDen2 = new Datum();
    nesmyslnyDen2.setRok(2023);
    nesmyslnyDen2.setMesic(3);
    nesmyslnyDen2.setDen(-2);
    System.out.println(nesmyslnyDen2);
}

Výstup:

Datum 9. listopad 2018
Mesic: listopad

Datum 24. prosinec 2018
Datum 31. prosinec 2018
Vanoce a Silvestr jsou ve stejnem mesici.

Neplatna hodnota mesice 13
Datum 11. NEPLATNY_MESIC_0 2020
Neplatna hodnota mesice -1
Datum 5. NEPLATNY_MESIC_0 2021
Neplatna hodnota dne 40
Datum 0. prosinec 2022
Neplatna hodnota dne -2
Datum 0. brezen 2023

Všimněte si, že přibyla ještě metoda getNazevMesice(), která vrací textovou reprezantaci místo čísla měsíce.

Také si všimněte, že se změnila metoda toString() tak, že se datum vypisuje pěkně s českým názvem měsíce, nikoliv číslem. Tedy nikoliv:

Datum 24. 12. 2018

Ale takto:

Datum 24. prosinec 2018

Část 3

Naprogramujte ještě vlastnost jeVPrestupnemRoce typu boolean, která bude jen pro čtení.

Upřesnění

Vlastnost bude true, pokud je rok z datumu přestupný, jinak false. Pravidlo přestupnosti roku je jedno z následujících.

Jak na to

Do třídy Datum je třeba vytvořit metodu:

Datum
  |
 ... (původní obsah vynechán)
  |
  +-- public boolean getJeVPrestupnemRoce()

Pozor, nepřidávejte žádnou vnitřní proměnnou do třídy Datum. Lokální proměnné v metodě getJeVPrestupnemRoce() samozřejmě používat můžete.

Výsledek

Všimněte si, že jsme takto vytvořili novou vlastnost bez toho, abychom přidávali vnitřní proměnnou. Taková vlastnost se někdy nazývá počítaná vlastnost (calculated property).

Část 4 (nepovinná)

Nakonec naprogramujte ještě vlastnost pocetDniVMesici typu int, která bude opět jen pro čtení. Počet dní je přesně definován pro každý měsíc konstatně (leden … 31, březen … 31, duben … 30, atd), s výjimkou února (february), který má buď 28 nebo 29 dní, podle toho, zda je v přestupném roce či nikoliv. Ale to už je hračka, protože vlastnost jeVPrestupnemRoce již máme z minula.

Jak na to

Do třídy Datum je třeba vytvořit metodu:

Datum
  |
 ... (původní obsah vynechán)
  |
  +-- public int getPocetDniVMesici()

Výsledek

Pokud se vám vše podaří, budete mít třídu Datum, která má 3 privátní vnitřní proměnné (ale protože jsou privátní, tak to není důležité), 1 klasickou metodu toString() a 5 vlastností. Z toho 3 pro čtení i zápis a 2 jen pro čtení. Všimněte si, že vlastnosti jsou jen myšlená věc na základě přítomnosti správně pojmenovaných metod (get a set). Tyto gettery a settery se vlastně ani nepovažují za plnoprávné metody. Proto jsem výše napsal, že třída Datum má jen 1 klasickou metodu (a je to toString()).

Odevzdání domácího úkolu

Nejprve appku/appky zbavte přeložených spustitelných souborů. Zařídíte to tak, že v IntelliJ IDEA vpravo zvolíte Maven Projects -> Lifecycle -> Clean. Úspěch se projeví tak, že v projektové složce zmizí podsložka target. Následně složku s projektem zabalte pomocí 7-Zipu pod jménem Ukol-CISLO-Vase_Jmeno.7z. (Případně lze použít prostý zip, například na Macu). Takto vytvořený archív nahrajte na Google Drive do Odevzdávárny.

Pokud byste chtěli odevzdat revizi úkolu (např. po opravě), zabalte ji a nahrajte ji na stejný Google Drive znovu, jen tentokrát se jménem Ukol-CISLO-Vase_Jmeno-verze2.7z.

Termín odevzdání je dva dny před další lekcí, nejpozději 23:59. Tedy pokud je další lekce ve čtvrtek, termín je úterý 23:59. Pokud úkol nebo revizi odevzdáte později, prosím pošlete svému opravujícímu kouči/lektorovi email nebo zprávu přes FB.