5. praktikum. Harjutused.
NB! Praktikumiülesandeid antakse alati varuga, et ka kõige kiirematel/kogenumatel lahendajatel jätkuks tegevust. Seega pole mõtet kurvastada, kui te ei jõua kõiki lahendada.
1. Lõbustuspargi simulaator
Selles ülesandes loome mitu lõbustuspargiteemalist klassi, millega saab uurida lõbustuspargi külastusi, piletitulu ja vanuspiirangute mõju. Selle tarvis tekitame külastaja klassi, mille isend oskab erinevaid lõbustusi külastada ja toimunud sündmused salvestada.
1.1. Looge aluskood
Selles ülesandes tuletame meelde isendiväljad, konstruktorid ja meetodid. Hilisemad ülesanded muudavad ja täiendavad kirjutatud aluskoodi.
- Looge klass Külastaja.- Lisage privaatne isendiväli külastuseKirjeldused, mis onList<String>tüüpi. AlgväärtustagekülastuseKirjeldusedkonstruktoris - looge seal selleks tarbeks uusArrayList<String>isend.
- Lisage voidmeetodlisaKirjeldus, mis võtab parameetriks sõne. Meetod lisab parameetriks antud sõnekülastuseKirjeldusedlisti.
- Lisage meetod kõikKirjeldused, mis tagastabkülastuseKirjeldused.
 
- Lisage privaatne isendiväli 
- Looge klass Vaateratas.- Lisage voidmeetodlõbusta, mis võtab parameetriksKülastajaisendi. Meetod lisab külastajale kirjelduse "külastasin vaateratast".
 
- Lisage 
- Looge klass Lõbustuspark.- Lisage privaatne isendiväli lõbustus, mis onVaateratastüüpi. Lisage konstruktor, mille parameetri kaudu saab lõbustuse väärtustada.
- Lisage voidmeetodalustaSeiklust, mis võtab parameetriksKülastajaisendi. Meetod väljastab ekraanile "alustan seiklust", kutsub välja lõbustuselõbustameetodi ja siis väljastab külastaja kõik kirjeldused.
 
- Lisage privaatne isendiväli 
- Looge klass Test, kus on ainult peameetod. Peameetodis tee järgnevat:- Looge isend Vaaterattast;
- Looge isend Lõbustuspargist, kasutades olemasolevat vaateratast;
- Looge isend Külastajast;
- Pange külastaja lõbustusparki seiklema.
 
- Looge isend 
1.2. Kasutage liidest
Selles ülesandes tuletame meelde liidese kõige lihtsama kasutusjuhu. Loome uue lõbustuse ja muudame lõbustusparki, nii et seal saab ainult vaateratta asemel kõiki sobilikke lõbustusi kasutada.
- Looge klass Lasketiir.- Lisage voidmeetodlõbusta, mis võtab parameetriksKülastajaisendi. KasutageMath.randomja genereerige täisarv vahemikus 0-20. Meetod lisab külastajale kirjelduse "tabasin lasketiirus N sihtmärki", kus N on genereeritud arv.
 
- Lisage 
- Looge liides Lõbustus. Liides kirjeldabvoidmeetoditlõbusta, mis võtab parameetriksKülastajaisendi.
- Muutke VaateratastjaLasketiiru, nii et nad realiseerivad liidestLõbustus.
- Muutke Lõbustusparki:- Muutke isendiväli lõbustustüüp listiks, mis hoiabLõbustusi. Nimetage isendiväli ümber:lõbustused.
- Muutke konstruktorit nii, et antakse ette List<Lõbustus>, mitte üksik lõbustus.
- Muutke alustaSeiklustmeetodit, nii et külastaja läbib järjest kõik lõbustused.
 
- Muutke isendiväli 
- Muutke Testpeameetodit:- Looge isend Lasketiirust;
- Lõbustuspargi loomisel andke argumendiks list, milles on vaateratas ja lasketiir.
 
- Looge isend 
1.3. Kohandage kangekaelset klassi
Meil on tihti vaja kasutada klasse, mida me ise muuta ei saa (nt Java sisse-ehitatud tüübid ja kood, mis on kirjutatud teiste ettevõtete poolt). Mõnikord on vaja panna mõni selline klass realiseerima mingit enda liidest. Sellisel juhul saab tekitada uue klassi, mis "mähib" olemasoleva klassi isendi ja kohandab ta vajaliku liidese realisatsiooniks, delegeerides põhitöö olemasolevale klassile. Seda tehnikat kutsutakse adapter pattern.
- Lisage enda koodi järgnev klass. Seda klassi ei tohi muuta (sh ei tohi lisada liideseid ega meetodeid).
public class Kloun {
  private String nimi;
  public Kloun(String nimi) {
    this.nimi = nimi;
  }
  public void esine(Külastaja külastaja) {
    külastaja.lisaKirjeldus("nägin klouni nimega " + nimi);
  }
}
- Looge klass LõbustavKloun, mis realiseerib liidestLõbustus.- Lisage privaatne Klountüüpi isendiväliklounja loo konstruktor, mille parameetri kaudu saab selle väärtustada.
- Realiseerige meetod lõbusta. Meetod kutsub klouni esinemise meetodit.
 
- Lisage privaatne 
- Muutke Testpeameetodit. LoogeKlouniisend (argumendiks andke enda lemmik klouninimi). KasutageLõbustavKlounklassi, et lisada kloun lõbustuspargi lõbustuste listi.
1.4. Muuda funktsionaalsust ilma klassi muutmata
Mõnikord on vaja lisada klassidele funktsionaalsust. Kui sama funktsionaalsus on vaja lisada mitmele klassile, siis ei ole praktiline koodi mitmesse klassi kopeerida-kleepida. Kui klassid realiseerivad sama liidest, saab neile hoopis liidestega trikitades koodi juurde "kleepida". Selle kohta öeldakse decorator pattern.
Selleks tuleb luua uus klass, mis realiseerib soovitud liidest, aga mis delegeerib kõik meetodid teisele sama liidest realiseeriva klassi isendile. Enne ja/või pärast delegeerimist saab decorator teha täiendavaid tegevusi.
- Muutke Külastajaklassi. Lisage privaatneinttüüpi isendivälivanus. Lisage vastavget-meetod. Lisage konstruktor, mille parameetri kaudu saab vanuse väärtustada.
- Looge klass VanuseKontrollija, mis realiseerib liidestLõbustus.- Lisage konstruktor, mis võtab kaks parameetrit: nõutudVanus(tüüpiint) jadelegaat(tüüpiLõbustus). Lisage vastavad privaatsed isendiväljad ja väärtustage need konstruktoris.
- Realiseerige meetod lõbusta. Meetodis kutsuge välja delegaadilõbustameetod (delegeeri ilma funktsionaalsust muutmata).
- Täiendage lõbustameetodit. Meetod peab kontrollima külastaja vanust. Kui külastaja vanus on nõutud vanusest väiksem, siis tuleb lisada külastajale kirjeldus "külastaja ei läbinud vanusekontrolli" ja delegaati mitte kasutada. Kui vanus on sobilik, siis tuleb kutsuda delegaadilõbustameetod.
 
- Lisage konstruktor, mis võtab kaks parameetrit: 
- Muutke Testpeameetodit.- Tekitage VanuseKontrollijaisend, kus nõutav vanus on 10 ja delegaat on lasketiiru isend. Pange lõbustuspargi argumendiks antavasse listi lasketiiru asemel hoopis vanusekontrollija, mis delegeerib lasketiirule.
- Tehke algse külastaja asemel kaks külastajat, üks vanusega 9 ja teine vanusega 11. Seigelge mõlemaga lõbustuspargis. Ainult 11-aastane külastaja peaks lasketiiru jõudma.
 
- Tekitage 
1.5. Delegaatide ahelad
Eelmises ülesandes loodud VanuseKontrollijat saab lisaks lasketiirule ka vaateratta ja klouniga kasutada, sest VanuseKontrollija oskab delegeerida ükskõik millisele Lõbustusele. Tegelikult ei pea ta üldse lõbustusele delegeerima - delegeerida võib ka mõnele teisele delegeerijale, lõbustus võib tulla alles pärast pikka delegeerimiste ahelat. 
Selles ülesandes kasutame taaskord decorator patternit ja loome TasulineLõbustus klassi. Seejärel ehitame delegeerimiste ahela - külastaja läbib kõigepealt vanusekontrolli, siis külastab lõbustust ja alles lõpus maksab piletiraha. 
- Muutke Külastajaklassi. Lisage privaatnedoubletüüpi isendivälikulud. LisagevoidmeetodlisaKulu, mis võtab parameetriksdoubletüüpi kulu ja suurendab selle võrra kulude isendivälja. Lisage meetodkuludeSumma, mis tagastab kulude isendivälja väärtuse.
- Muutke Lõbustusparkklassi, nii et pärast kõigi lõbustuste külastamist väljastatakse ka lõbutsemisel tehtud kulutuste summa.
- Looge klass TasulineLõbustus, mis realiseerib liidestLõbustus.- Lisage konstruktor, mis võtab kaks parameetrit: hind (tüüpi double) ja delegaat (tüüpiLõbustus). Lisage vastavad privaatsed isendiväljad ja väärtustage need konstruktoris.
- Realiseerige meetod lõbusta. Meetod kutsub delegaadilõbustameetodi ja pärast selle lõpetamist lisab külastajale ettemääratud kulu ja kirjelduse "tasusin külastuse eest " + hind.
 
- Lisage konstruktor, mis võtab kaks parameetrit: hind (tüüpi 
- Muutke Testpeameetodit.- Tekitage TasulineLõbustusisend, kus hind on 2.25 ja delegaat on vaateratta isend. Kasutage lõbustuspargi argumendiks antavas listis vaateratta asemel tasulist vaateratast.
- Tekitage TasulineLõbustusisend, kus hind on 1.5 ja delegaat on lasketiiru isend. AndkeVanuseKontrollijaargumendiks lasketiiru asemel tasuline lasketiir (vanusekontrollija delegeerib tasulisele külastusele, mis delegeerib lasketiirule).
- Kirjeldage kommentaaris, mis juhtuks, kui hoopis TasulineLõbustusdelegeeriks vanusekontrolliga lasketiirule (objektid on üksteise sees teises järjekorras). Kuidas koodi käitumine muutuks?
 
- Tekitage 
2. Failipuu läbimine
Javas on sisseehitatud meetod Files.walkFileTree, mis läbib rekursiivselt etteantud failisüsteemi kausta ja kõik selles sisalduvad failid. Iga leitud kausta ja faili kohta antakse meetodi argumendiks antud vaatleja-objektile teada. 
Seotud javadoc: 
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/FileVisitor.html 
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/Path.html 
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/Files.html
Kui kompilaator hakkab exceptionite teemal virisema ("unhandled exception .."), siis lisage selle meetodi päisesse deklaratsioon throws Exception. (Kui teie IDE soovitab selle asemel try-catch plokke kasutada, siis ära teda kuula.) 
public static void main(String[] args) throws Exception {
}
2.1. Failide väljastamine
Selles ülesandes kasutame Files.walkFileTree meetodit, et väljastada ekraanile kõik etteantud kaustas olevad failid. 
- Looge klass FailiVaatleja, mis realiseerib liideseFileVisitor<Path>.- Kõigi FileVisitorliidese meetodite tagastustüüp onFileVisitResult. Meie programmis on sobilik tagastada kõigis liidese meetoditesFileVisitResult.CONTINUE.
- Väljastage visitFilemeetodis parameetriga ette antud failinimi ekraanile.
 
- Kõigi 
- Looge klass FailiTest, kus on peameetod.- Kasutage käsureal sisestatud kaustanime. Loo sellest Pathobjekt, kasutadesPath.ofmeetodit. Käsurea parameetritest oli juttu ka 2. praktikumis. (Kui sul on vana Java versioon, siis kasutaPath.ofasemelPaths.get.)
- Kontrollige, et loodud tee on kaust, kasutades Files.isDirectorymeetodit. Kui käsureal sisestatud asukoht ei viita kaustale, siis väljasta veateade ja lõpeta programmi töö (returnpeameetodist).
- Looge FailiVaatlejaisend.
- Kutsuge Files.walkFileTreemeetod. Andke argumentideks loodud tee ja failivaatleja. Käivitage programm ja veenduge, et failivaatleja väljastab etteantud kausta sisu, selles olevate kaustade sisud jne.
 
- Kasutage käsureal sisestatud kaustanime. Loo sellest 
2.2. Failide sorteerimine
Selles ülesandes täiendame oma failinimede väljastajat, nii et nimed väljastatakse sorteeritud järjekorras. Sorteerimise järjekorra määramiseks kasutame Comparator<T> liidest. 
Comparator liidese javadoc: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Comparator.html
- Muutke FailiVaatlejaklassi. Lisage privaatneList<String>tüüpi isendivälifailiNimed. Väärtustage see konstruktoris uueArrayList<String>isendiga. Lisage vastavget-meetod.
- Muutke visitFilemeetodit, nii et iga külastatud fail lisataksefailiNimedlisti.Pathobjekti võib sõneks teisendada, kasutadestoStringmeetodit. Ärge siin meetodis midagi ekraanile väljastage.
- Muutke FailiTestpeameetodit. PärastwalkFileTreemeetodi lõppu sorteeri failivaatlejasse kogunenud failide nimed ja väljastage need ekraanile. Sorteerimiseks kasutageCollections.sortmeetodit. Veenduge, et nimed on tähestikujärjekorras.
- Lisage klass NimeVõrdleja, mis realiseerib liidestComparator<String>(toimib väga sarnaseltComparableliidesega). Realiseerigecomparemeetod nii, et sõned sorteeritakse tavalisest vastupidises järjekorras (["a", "b", "c"]vs["c", "b", "a"]). Vihje:Comparatorrealiseerimiseks peab looma ainultcomparemeetodi (ära default meetodeid üle kirjuta).
- Muutke peameetodis Collections.sortväljakutset, nii et sorteerimisalgoritm kasutaks teie loodudNimeVõrdlejat(Collections.sort(List<T>, Comparator<T>)). Veenduge, et nüüd sorteeritakse failide nimed tähed-enne-numbreid.