Mikäli kaipaat apuja NetBeanssin käytön aloittamiseen tutustu seuraaviin linkeihin: NetBeans aloitusohje. Valitse kuitenkin kurssiksi XXX-ohja-kertaus

Tavara, Matkalaukku ja Lastiruuma

Tavara, Matkalaukku ja Lastiruuma

Tässä tehtäväsarjassa tehdään luokat Tavara, Matkalaukku ja Lastiruuma, joiden avulla harjoitellaan olioita, jotka sisältävät toisia olioita.

Mikäli tehtävä tuottaa haasteita tutustu seuraaviin linkkeihin: Ohjelmoinnin perusteiden kertaus

Tavara-luokka

Tee luokka Tavara, josta muodostetut oliot vastaavat erilaisia tavaroita. Tallennettavat tiedot ovat tavaran nimi ja paino (kg).

Lisää luokkaan seuraavat metodit:

Seuraavassa on luokan käyttöesimerkki:

public class Main {
    public static void main(String[] args) {
        Tavara kirja = new Tavara("Aapiskukko", 2);
        Tavara puhelin = new Tavara("Nokia 3210", 1);

        System.out.println("Kirjan nimi: " + kirja.getNimi());
        System.out.println("Kirjan paino: " + kirja.getPaino());

        System.out.println("Kirja: " + kirja);
        System.out.println("Puhelin: " + puhelin);
    }
}

Ohjelman tulostuksen tulisi olla seuraava:

Kirjan nimi: Aapiskukko
Kirjan paino: 2
Kirja: Aapiskukko (2 kg)
Puhelin: Nokia 3210 (1 kg)

Matkalaukku-luokka

Tee luokka Matkalaukku. Matkalaukkuun liittyy tavaroita ja maksimipaino, joka määrittelee tavaroiden suurimman mahdollisen yhteispainon.

Lisää luokkaan seuraavat metodit:

Tavarat kannattaa tallentaa ArrayList-olioon:

ArrayList<Tavara> tavarat = new ArrayList<Tavara>();

Luokan Matkalaukku tulee valvoa, että sen sisältämien tavaroiden yhteispaino ei ylitä maksimipainoa. Jos maksimipaino ylittyisi lisättävän tavaran vuoksi, metodi lisaaTavara ei saa lisätä uutta tavaraa laukkuun.

Seuraavassa on luokan käyttöesimerkki:

public class Main {
    public static void main(String[] args) {
        Tavara kirja = new Tavara("Aapiskukko", 2);
        Tavara puhelin = new Tavara("Nokia 3210", 1);
        Tavara tiiliskivi = new Tavara("tiiliskivi", 4);

        Matkalaukku matkalaukku = new Matkalaukku(5);
        System.out.println(matkalaukku);

        matkalaukku.lisaaTavara(kirja);
        System.out.println(matkalaukku);

        matkalaukku.lisaaTavara(puhelin);
        System.out.println(matkalaukku);

        matkalaukku.lisaaTavara(tiiliskivi);
        System.out.println(matkalaukku);
    }
}

Ohjelman tulostuksen tulisi olla seuraava:

0 tavaraa (0 kg)
1 tavaraa (2 kg)
2 tavaraa (3 kg)
2 tavaraa (3 kg)

Kielenhuoltoa

Ilmoitukset "0 tavaraa" ja "1 tavaraa" eivät ole kovin hyvää suomea – paremmat muodot olisivat "ei tavaroita" ja "1 tavara". Tee tämä muutos luokkaan Matkalaukku.

Nyt edellisen ohjelman tulostuksen tulisi olla seuraava:

ei tavaroita (0 kg)
1 tavara (2 kg)
2 tavaraa (3 kg)
2 tavaraa (3 kg)

Kaikki tavarat

Lisää luokkaan Matkalaukku seuraavat metodit:

Seuraavassa on luokan käyttöesimerkki:

public class Main {
    public static void main(String[] args) {
        Tavara kirja = new Tavara("Aapiskukko", 2);
        Tavara puhelin = new Tavara("Nokia 3210", 1);
        Tavara tiiliskivi = new Tavara("tiiliskivi", 4);

        Matkalaukku matkalaukku = new Matkalaukku(10);
        matkalaukku.lisaaTavara(kirja);
        matkalaukku.lisaaTavara(puhelin);
        matkalaukku.lisaaTavara(tiiliskivi);

        System.out.println("Matkalaukussa on seuraavat tavarat:");
        matkalaukku.tulostaTavarat();
        System.out.println("Yhteispaino: " + matkalaukku.yhteispaino() + " kg");
    }
}

Ohjelman tulostuksen tulisi olla seuraava:

Matkalaukussa on seuraavat tavarat:
Aapiskukko (2 kg)
Nokia 3210 (1 kg)
Tiiliskivi (4 kg)
Yhteispaino: 7 kg

Muokkaa myös luokkaasi siten, että käytät vain kahta oliomuuttujaa. Toinen sisältää maksimipainon, toinen on lista laukussa olevista tavaroista.

Raskain tavara

Lisää vielä luokkaan Matkalaukku metodi raskainTavara, joka palauttaa painoltaan suurimman tavaran. Jos yhtä raskaita tavaroita on useita, metodi voi palauttaa minkä tahansa niistä. Metodin tulee palauttaa olioviite. Jos laukku on tyhjä, palauta arvo null.

Seuraavassa on luokan käyttöesimerkki:

public class Main {
    public static void main(String[] args) {
        Tavara kirja = new Tavara("Aapiskukko", 2);
        Tavara puhelin = new Tavara("Nokia 3210", 1);
        Tavara tiiliskivi = new Tavara("Tiiliskivi", 4);

        Matkalaukku matkalaukku = new Matkalaukku(10);
        matkalaukku.lisaaTavara(kirja);
        matkalaukku.lisaaTavara(puhelin);
        matkalaukku.lisaaTavara(tiiliskivi);

        Tavara raskain = matkalaukku.raskainTavara();
        System.out.println("Raskain tavara: " + raskain);
    }
}

Ohjelman tulostuksen tulisi olla seuraava:

Raskain tavara: Tiiliskivi (4 kg)

Lastiruuma-luokka

Tee luokka Lastiruuma, johon liittyvät seuraavat metodit:

Tallenna matkalaukut sopivaan ArrayList-rakenteeseen.

Luokan Lastiruuma tulee valvoa, että sen sisältämien matkalaukkujen yhteispaino ei ylitä maksimipainoa. Jos maksimipaino ylittyisi uuden matkalaukun vuoksi, metodi lisaaMatkalaukku ei saa lisätä uutta matkalaukkua.

Seuraavassa on luokan käyttöesimerkki:

public class Main {
    public static void main(String[] args) {
        Tavara kirja = new Tavara("Aapiskukko", 2);
        Tavara puhelin = new Tavara("Nokia 3210", 1);
        Tavara tiiliskivi = new Tavara("tiiliskivi", 4);

        Matkalaukku matinLaukku = new Matkalaukku(10);
        matinLaukku.lisaaTavara(kirja);
        matinLaukku.lisaaTavara(puhelin);

        Matkalaukku pekanLaukku = new Matkalaukku(10);
        pekanLaukku.lisaaTavara(tiiliskivi);

        Lastiruuma lastiruuma = new Lastiruuma(1000);
        lastiruuma.lisaaMatkalaukku(matinLaukku);
        lastiruuma.lisaaMatkalaukku(pekanLaukku);

        System.out.println(lastiruuma);
    }
}

Ohjelman tulostuksen tulisi olla seuraava:

2 matkalaukkua (7 kg)

Lastiruuman sisältö

Lisää luokkaan Lastiruuma metodi public void tulostaTavarat(), joka tulostaa kaikki lastiruuman matkalaukuissa olevat tavarat.

Seuraavassa on luokan käyttöesimerkki:

public class Main {
    public static void main(String[] args) {
        Tavara kirja = new Tavara("Aapiskukko", 2);
        Tavara puhelin = new Tavara("Nokia 3210", 1);
        Tavara tiiliskivi = new Tavara("tiiliskivi", 4);

        Matkalaukku matinLaukku = new Matkalaukku(10);
        matinLaukku.lisaaTavara(kirja);
        matinLaukku.lisaaTavara(puhelin);

        Matkalaukku pekanLaukku = new Matkalaukku(10);
        pekanLaukku.lisaaTavara(tiiliskivi);

        Lastiruuma lastiruuma = new Lastiruuma(1000);
        lastiruuma.lisaaMatkalaukku(matinLaukku);
        lastiruuma.lisaaMatkalaukku(pekanLaukku);

        System.out.println("Ruuman matkalaukuissa on seuraavat tavarat:");
        lastiruuma.tulostaTavarat();
    }
}

Ohjelman tulostuksen tulisi olla seuraava:

Ruuman matkalaukuissa on seuraavat tavarat:
Aapiskukko (2 kg)
Nokia 3210 (1 kg)
tiiliskivi (4 kg)

Paljon tiiliskiviä

Testataan vielä, että lastiruuman toiminta on oikea eikä maksimipaino pääse ylittymään. Tee Main-luokkaan metodi public static void lisaaMatkalaukutTiiliskivilla(Lastiruuma lastiruuma), joka lisää parametrina annettuun lastiruumaan 100 matkalaukkua, joissa jokaisessa on yksi tiiliskivi. Tiiliskivien painot ovat 1, 2, 3, ..., 100 kg.

Ohjelman runko on seuraava:

public class Main {
    public static void main(String[] args) {
        Lastiruuma lastiruuma = new Lastiruuma(1000);
        lisaaMatkalaukutTiiliskivilla(lastiruuma);
        System.out.println(lastiruuma);
    }

    public static void lisaaMatkalaukutTiiliskivilla(Lastiruuma lastiruuma) {
        // 100 matkalaukun lisääminen, jokaiseen tulee tiiliskivi
    }
}

Ohjelman tulostus on seuraava:

44 matkalaukkua (990 kg)

Lempinimet

Lempinimet

Mikäli tehtävä tuottaa haasteita tutustu seuraaviin linkkeihin: HashMap

Luo main-metodissa uusi HashMap<String,String>-olio. Tallenna tähän HashMappiin seuraavien henkilöiden nimet ja lempinimet niin, että nimi on avain ja lempinimi on arvo. Käytä pelkkiä pieniä kirjaimia.

Tämän jälkeen hae HashMapistä mikaelin lempinimi ja tulosta se.

Testit edellyttävät että kirjoitat nimet pienellä alkukirjaimella.

Tavaroita ja laatikoita

Tavaroita ja laatikoita

Talletettavia

Mikäli tehtävä tuottaa haasteita tutustu seuraaviin linkkeihin: Rajapinta

Muuton yhteydessa tarvitaan muuttolaatikoita. Laatikoihin talletetaan erilaisia esineitä. Kaikkien laatikoihin talletettavien esineiden on toteutettava seuraava rajapinta:

public interface Talletettava {
    double paino();
}

Lisää rajapinta ohjelmaasi. Rajapinta lisätään melkein samalla tavalla kuin luokka, new Java class sijaan valitaan new Java interface.

Tee rajapinnan toteuttavat luokat Kirja ja CDLevy. Kirja saa konstruktorin parametreina kirjan kirjoittajan (String), kirjan nimen (String), ja kirjan painon (double). CD-Levyn konstruktorin parametreina annetaan artisti (String), levyn nimi (String), ja julkaisuvuosi (int). Kaikkien CD-levyjen paino on 0.1 kg.

Muista toteuttaa luokilla myös rajapinta Talletettava. Luokkien tulee toimia seuraavasti:

    public static void main(String[] args) {
        Kirja kirja1 = new Kirja("Fedor Dostojevski", "Rikos ja Rangaistus", 2);
        Kirja kirja2 = new Kirja("Robert Martin", "Clean Code", 1);
        Kirja kirja3 = new Kirja("Kent Beck", "Test Driven Development", 0.5);

        CDLevy cd1 = new CDLevy("Pink Floyd", "Dark Side of the Moon", 1973);
        CDLevy cd2 = new CDLevy("Wigwam", "Nuclear Nightclub", 1975);
        CDLevy cd3 = new CDLevy("Rendezvous Park", "Closer to Being Here", 2012);

        System.out.println(kirja1);
        System.out.println(kirja2);
        System.out.println(kirja3);
        System.out.println(cd1);
        System.out.println(cd2);
        System.out.println(cd3);
    }

Tulostus:

Fedor Dostojevski: Rikos ja Rangaistus
Robert Martin: Clean Code
Kent Beck: Test Driven Development
Pink Floyd: Dark Side of the Moon (1973)
Wigwam: Nuclear Nightclub (1975)
Rendezvous Park: Closer to Being Here (2012)

Huom! Painoa ei ilmoiteta tulostuksessa.

Laatikko

Tee luokka laatikko, jonka sisälle voidaan tallettaa Talletettava-rajapinnan toteuttavia tavaroita. Laatikko saa konstruktorissaan parametrina laatikon maksimikapasiteetin kiloina. Laatikkoon ei saa lisätä enempää tavaraa kuin sen maksimikapasiteetti määrää. Laatikon sisältämien tavaroiden paino ei siis koskaan saa olla yli laatikon maksimikapasiteetin.

Seuraavassa esimerkki laatikon käytöstä:

    public static void main(String[] args) {
        Laatikko laatikko = new Laatikko(10);

        laatikko.lisaa( new Kirja("Fedor Dostojevski", "Rikos ja Rangaistus", 2) ) ;
        laatikko.lisaa( new Kirja("Robert Martin", "Clean Code", 1) );
        laatikko.lisaa( new Kirja("Kent Beck", "Test Driven Development", 0.7) );

        laatikko.lisaa( new CDLevy("Pink Floyd", "Dark Side of the Moon", 1973) );
        laatikko.lisaa( new CDLevy("Wigwam", "Nuclear Nightclub", 1975) );
        laatikko.lisaa( new CDLevy("Rendezvous Park", "Closer to Being Here", 2012) );

        System.out.println( laatikko );
    }

Tulostuu

Laatikko: 6 esinettä, paino yhteensä 4.0 kiloa

Huom: koska painot esitetään doubleina, saattaa laskutoimituksissa tulla pieniä pyöristysvirheitä. Tehtävässä ei tarvitse välittää niistä.

Laatikon paino

Jos teit laatikon sisälle oliomuuttujan double paino, joka muistaa laatikossa olevien esineiden painon, korvaa se metodilla, joka laskee painon:

public class Laatikko {
    //...

    public double paino() {
        double paino = 0;
        // laske laatikkoon talletettujen tavaroiden yhteispaino
        return paino;
    }
}

Kun tarvitset laatikon sisällä painoa esim. uuden tavaran lisäyksen yhteydessä, riittää siis kutsua laatikon painon laskevaa metodia.

Metodi toki voisi palauttaa myös oliomuuttujan arvon. Harjoittelemme tässä kuitenkin tilannetta, jossa oliomuuttujaa ei tarvitse eksplisiittisesti ylläpitää vaan se voidaan tarpeentullen laskea. Seuraavan tehtävän jälkeen laatikossa olevaan oliomuuttujaan talletettu painotieto ei kuitenkaan välttämättä enää toimisi. Miksi?

Laatikkokin on talletettava!

Rajapinnan Talletettava toteuttaminen siis edellyttää että luokalla on metodi double paino(). Laatikollehan lisättiin juuri tämä metodi. Laatikosta voidaan siis tehdä talletettava!

Laatikot ovat oliota joihin voidaan laittaa Talletettava-rajapinnan toteuttavia olioita. Laatikot toteuttavat itsekin rajapinnan. Eli laatikon sisällä voi olla myös laatikoita!

Kokeile että näin varmasti on, eli tee ohjelmassasi muutama laatikko, laita laatikoihin tavaroita ja laita pienempiä laatikoita isompien laatikoiden sisään. Kokeile myös mitä tapahtuu kun laitat laatikon itsensä sisälle. Miksi näin käy?

Joukkoja

Joukkoja

Mikäli tehtävä tuottaa haasteita tutustu seuraaviin linkkeihin: Olioiden monimuotoisuus ja Luokkien organisointi pakkauksiin

Tässä tehtävässä teemme eliöita ja eliöistä koostuvia laumoja jotka liikkuvat ympäriinsä. Eliöiden sijaintien ilmoittamiseen käytetään kaksiulotteista koordinaatistoa. Jokaiseen sijaintiin liittyy kaksi lukua, x- ja y-koordinaatti. Koordinaatti x kertoo, kuinka pitkällä "nollapisteestä" mitattuna sijainti on vaakasuunnassa, ja koordinaatti y vastaavasti kuinka pitkällä sijainti on pystysuunnassa. Jos koordinaatiston käsite ei ole tuttu, voit lukea siitä lisää esimerkiksi wikipediasta.

Tehtävän mukana tulee rajapinta Siirrettava, joka kuvaa asiaa jota voidaan siirtää paikasta toiseen. Rajapinta sisältää metodin void siirra(int dx, int dy). Parametri dx kertoo, paljonko asia siirtyy x-akselilla ja dy y-akselilla.

Tehtävässä toteutat luokat Elio ja Lauma, jotka molemmat ovat siirrettäviä. Toteuta kaikki toiminnallisuus pakkaukseen siirrettava.

Elio-luokan toteuttaminen

Luo pakkaukseen siirrettava luokka Elio, joka toteuttaa rajapinnan Siirrettava. Eliön tulee tietää oma sijaintinsa (x, y -koordinaatteina). Luokan Elio APIn tulee olla seuraava:

Kokeile luokan Elio toimintaa seuraavalla esimerkkikoodilla.

     Elio elio = new Elio(20, 30);
     System.out.println(elio);
     elio.siirra(-10, 5);
     System.out.println(elio);
     elio.siirra(50, 20);
     System.out.println(elio);
x: 20; y: 30
x: 10; y: 35
x: 60; y: 55

Lauman toteutus

Luo seuraavaksi pakkaukseen siirrettava luokka Lauma, joka toteuttaa rajapinnan Siirrettava. Lauma koostuu useasta Siirrettava-rajapinnan toteutavasta oliosta, jotka tulee tallettaa esimerkiksi listarakenteeseen.

Luokalla Lauma tulee olla seuraavanlainen API.

Kokeile ohjelmasi toimintaa alla olevalla esimerkkikoodilla.

    Lauma lauma = new Lauma();
    lauma.lisaaLaumaan(new Elio(73, 56));
    lauma.lisaaLaumaan(new Elio(57, 66));
    lauma.lisaaLaumaan(new Elio(46, 52));
    lauma.lisaaLaumaan(new Elio(19, 107));
    System.out.println(lauma);
x: 73; y: 56
x: 57; y: 66
x: 46; y: 52
x: 19; y: 107

Sensorit ja lämpötilan mittausta

Sensorit ja lämpötilan mittausta

Mikäli tehtävä tuottaa haasteita tutustu seuraaviin linkkeihin: Poikkeustilanteet ja Luokan ominaisuuksien periminen

Kakki sovelluksessa oleva koodi tulee sijoittaa pakkaukseen sovellus.

Käytössämme on seuraava rajapinta:

public interface Sensori {
    boolean onPaalla();  // palauttaa true jos sensori on päällä
    void paalle();       // käynnistä sensorin
    void poisPaalta();   // sulkee sensorin
    int mittaa();        // palauttaa sensorin lukeman jos sensori on päällä
                         // jos sensori ei päällä heittää poikkeuksen IllegalStateException
}

Vakiosensori

Tee luokka Vakiosensori joka toteuttaa rajapinnan Sensori.

Vakiosensori on koko ajan päällä. Metodien paalle ja poisPaalta kutsuminen ei tee mitään. Vakiosensorilla tulee olla konstruktori, jonka parametrina on kokonaisluku. Metodikutsu mittaa palauttaa aina konstruktorille parametrina annetun luvun.

Esimerkki:

public static void main(String[] args) {
  Vakiosensori kymppi = new Vakiosensori(10);
  Vakiosensori miinusViis = new Vakiosensori(-5);

  System.out.println( kymppi.mittaa() );
  System.out.println( miinusViis.mittaa() );

  System.out.println( kymppi.onPaalla() );
  kymppi.poisPaalta();
  System.out.println( kymppi.onPaalla() );
}

Tulostuu:

10
-5
true
true

Lampomittari

Tee luokka Lampomittari joka toteuttaa rajapinnan Sensori.

Aluksi lämpömittari on poissa päältä. Kutsuttaessa metodia mittaa kun mittari on päällä mittari arpoo luvun väliltä -30...30 ja palauttaa sen kutsujalle. Jos mittari ei ole päällä, heitetään poikkeus IllegalStateException.

Keskiarvosensori

Tee luokka Keskiarvosensori joka toteuttaa rajapinnan Sensori.

Keskiarvosensori sisältää useita sensoreita. Rajapinnan Sensori määrittelemien metodien lisäksi keskiarvosensorilla on metodi public void lisaaSensori(Sensori lisattava) jonka avulla keskiarvosensorin hallintaan lisätään uusi sensori.

Keskiarvosensori on päällä silloin kuin kaikki sen sisältävät sensorit ovat päällä. Kun keskiarvosensori käynnistetään, täytyy kaikkien sen sisältävien sensorien käynnistyä jos ne eivät ole käynnissä. Kun keskiarvosensori suljetaan, täytyy ainakin yhden sen sisältävän sensorin mennä pois päältä. Saa myös käydä niin että kaikki sen sisältävät sensorit menevät pois päältä.

Keskiarvosensorin metodi mittaa palauttaa sen sisältämien sensoreiden lukemien keskiarvon (koska paluuarvo on int, pyöristyy lukema alaspäin kuten kokonaisluvuilla tehdyissä jakolaskuissa). Jos keskiarvosensorin metodia mittaa kutsutaan sensorin ollessa poissa päältä, tai jos keskiarvosensorille ei vielä ole lisätty yhtään sensoria heitetään poikkeus IllegalStateException.

Seuraavassa sensoreja käyttävä esimerkkiohjelma (huomaa, että sekä Lämpömittarin että Keskiarvosensorin konstruktorit ovat parametrittomia):

public static void main(String[] args) {
    Sensori kumpula = new Lampomittari();         
    kumpula.paalle();
    System.out.println("lämpötila Kumpulassa "+kumpula.mittaa() + " astetta");
    
    Sensori kaisaniemi = new Lampomittari();        
    Sensori helsinkiVantaa = new Lampomittari();
        
    Keskiarvosensori paakaupunki = new Keskiarvosensori();
    paakaupunki.lisaaSensori(kumpula);
    paakaupunki.lisaaSensori(kaisaniemi);
    paakaupunki.lisaaSensori(helsinkiVantaa);
        
    paakaupunki.paalle();
    System.out.println("lämpötila Pääkaupunkiseudulla "+paakaupunki.mittaa() + " astetta");     
}

tulostuu (tulostetut lukuarvot riippuvat tietenkin arvotuista lämpötiloista):

lämpötila Kumpulassa -7 astetta
lämpötila Pääkaupunkiseudulla -10 astetta

Huom: kannatata käyttää Vakiosensori-oliota keskiarvosensorin testaamiseen!

Kaikki mittaukset

Lisää luokalle Keskiarvosensori metodi public List<Integer> mittaukset(), joka palauttaa listana kaikkien keskiarvosensorin avulla suoritettujen mittausten tulokset. Seuraavassa esimerkki metodin toiminnasta:

public static void main(String[] args) {
    Sensori kumpula = new Lampomittari();         
    Sensori kaisaniemi = new Lampomittari();        
    Sensori helsinkiVantaa = new Lampomittari();
        
    Keskiarvosensori paakaupunki = new Keskiarvosensori();
    paakaupunki.lisaaSensori(kumpula);
    paakaupunki.lisaaSensori(kaisaniemi);
    paakaupunki.lisaaSensori(helsinkiVantaa);
        
    paakaupunki.paalle();
    System.out.println("lämpötila Pääkaupunkiseudulla "+paakaupunki.mittaa() + " astetta");     
    System.out.println("lämpötila Pääkaupunkiseudulla "+paakaupunki.mittaa() + " astetta");    
    System.out.println("lämpötila Pääkaupunkiseudulla "+paakaupunki.mittaa() + " astetta");    

    System.out.println("mittaukset: "+paakaupunki.mittaukset());
}

tulostuu (tulostetut lukuarvot riippuvat jälleen arvotuista lämpötiloista):

lämpötila Pääkaupunkiseudulla -10 astetta
lämpötila Pääkaupunkiseudulla -4 astetta
lämpötila Pääkaupunkiseudulla 5 astetta

mittaukset: [-10, -4, 5]

Tiedoston analyysi

Tiedoston analyysi

Mikäli tehtävä tuottaa haasteita tutustu seuraaviin linkkeihin: Tiedoston lukeminen ja Poikkeustilanteet

Tässä tehtävässä tehdään sovellus tiedoston rivi- ja merkkimäärän laskemiseen.

Rivien laskeminen

Tee pakkaukseen tiedosto luokka Analyysi, jolla on konstruktori public Analyysi(File tiedosto). Toteuta luokalle metodi public int rivimaara(), joka palauttaa konstruktorille annetun tiedoston rivimäärän.

Metodi ei saa olla "kertakäyttöinen", eli sen pitää tuottaa oikea tulos myös usealla peräkkäisellä kutsulla. Huomaa, että kun teet tiedostoa vastaavan Scanner-olion, ja luet tiedoston koko sisällön nextLine-komennoilla, et voi käyttää enää samaa skanneria tiedoston uudelleenlukemiseen!

Huom: jos testit sanovat timeout, et todennäköisesti muista lukea tiedostoa ollenkaan, eli nextLine-kutsut puuttuvat!

Merkkien laskeminen

Toteuta luokkaan Analyysi metodi public int merkkeja(), joka palauttaa luokan konstruktorille annetun tiedoston merkkien määrän.

Metodi ei saa olla "kertakäyttöinen", eli sen pitää tuottaa oikea tulos myös usealla peräkkäisellä kutsulla.

Voit itse päättää miten reagoidaan jos konstruktorin parametrina saatua tiedostoa ei ole olemassa.

Projektisi testipakkauksessa on testausta varten tiedosto testitiedosto.txt. Ohjelmasta avatessa tiedoston nimeksi tulee antaa test/testitiedosto.txt. Tiedoston sisältö on seuraava:

rivejä tässä on 3 ja merkkejä 
koska rivinvaihdotkin ovat
merkkejä

Ohjelman toiminta testaustiedostolla:

    File tiedosto = new File("src/testitiedosto.txt");
    Analyysi analyysi = new Analyysi(tiedosto);
    System.out.println("Rivejä: " + analyysi.rivimaara());
    System.out.println("Merkkejä: " + analyysi.merkkeja());
Rivejä: 3
Merkkejä: 67

Varastointia

Varastointia

Mikäli tehtävä tuottaa haasteita tutustu seuraaviin linkkeihin: Käyttäjän syötteen lukeminen ja Luokan ominaisuuksien periminen

Tehtäväpohjassa tulee mukana luokka Varasto, jonka tarjoamat konstruktorit ja metodit ovat seuraavat:

Tehtävässä rakennetaan Varasto-luokasta useampia erilaisia varastoja. Huom! Toteuta kaikki luokat pakkaukseen varastot.

Tuotevarasto, vaihe 1

Luokka Varasto hallitsee tuotteen määrään liittyvät toiminnot. Nyt tuotteelle halutaan lisäksi tuotenimi ja nimen käsittelyvälineet. Ohjelmoidaan Tuotevarasto Varaston aliluokaksi! Toteutetaan ensin pelkkä yksityinen oliomuuttuja tuotenimelle, konstruktori ja getteri nimikentälle:

Muista millä tavoin konstruktori voi ensi toimenaan suorittaa yliluokan konstruktorin!

Käyttöesimerkki:

        Tuotevarasto mehu = new Tuotevarasto("Juice", 1000.0);
        mehu.lisaaVarastoon(1000.0);
        mehu.otaVarastosta(11.3);
        System.out.println(mehu.getNimi()); // Juice
        System.out.println(mehu);           // saldo = 988.7, tilaa 11.3
Juice
saldo = 988.7, vielä tilaa 11.3

Tuotevarasto, vaihe 2

Kuten edellisestä esimerkistä näkee, Tuotevarasto-olion perimä toString() ei tiedä (tietenkään!) mitään tuotteen nimestä. Asialle on tehtävä jotain! Lisätään samalla myös setteri tuotenimelle:

Uuden toString()-metodin voisi toki ohjelmoida käyttäen yliluokalta perittyjä gettereitä, joilla perittyjen, mutta piilossa pidettyjen kenttien arvoja saa käyttöönsä. Koska yliluokkaan on kuitenkin jo ohjelmoitu tarvittava taito varastotilanteen merkkiesityksen tuottamiseen, miksi nähdä vaivaa sen uudelleen ohjelmointiin. Käytä siis hyväksesi perittyä toStringiä.

Muista miten korvattua metodia voi kutsua aliluokassa!

Käyttöesimerkki:

        Tuotevarasto mehu = new Tuotevarasto("Juice", 1000.0);
        mehu.lisaaVarastoon(1000.0);
        mehu.otaVarastosta(11.3);
        System.out.println(mehu.getNimi()); // Juice
        mehu.lisaaVarastoon(1.0);
        System.out.println(mehu);           // Juice: saldo = 989.7, tilaa 10.299999999999955
Juice
Juice: saldo = 989.7, tilaa 10.299999999999955

Muutoshistoria

Toisinaan saattaa olla kiinostavaa tietää, millä tavoin jonkin tuotteen varastotilanne muuttuu: onko varasto usein hyvin vajaa, ollaanko usein ylärajalla, onko vaihelu suurta vai pientä, jne. Varustetaan siksi Tuotevarasto-luokka taidolla muistaa tuotteen määrän muutoshistoriaa.

Aloitetaan apuvälineen laadinnalla.

Muutoshistorian muistamisen voisi toki toteuttaa suoraankin ArrayList<Double>-oliona luokassa Tuotevarasto, mutta nyt laaditaan kuitenkin oma erikoistettu väline tähän tarkoitukseen. Väline toteutetaan kapseloimalla ArrayList<Double>-olio.

Muutoshistoria-luokan julkiset konstruktorit ja metodit:

Muutoshistoria.java, vaihe 2

Täydennä Muutoshistoria-luokkaa analyysimetodein:

Muutoshistoria.java, vaihe 3

Täydennä Muutoshistoria-luokkaa analyysimetodein:

Ohjeen varianssin laskemiseksi voit katsoa esimerkiksi Wikipediasta kohdasta populaatio- ja otosvarianssi. Esimerkiksi lukujen 3, 2, 7, 2 keskiarvo on 3.5, joten otosvarianssi on ((3 - 3.5)² + (2 - 3.5)² + (7 - 3.5)² + (2 - 3.5)²)/(4 - 1) ≈ 5,666667.)

MuistavaTuotevarasto, vaihe 1

Toteuta luokan Tuotevarasto aliluokkana MuistavaTuotevarasto. Uusi versio tarjoaa vanhojen lisäksi varastotilanteen muutoshistoriaan liittyviä palveluita. Historiaa hallitaan Muutoshistoria-oliolla.

Julkiset konstruktorit ja metodit:

Huomaa että tässä esiversiossa historia ei vielä toimi kunnolla; nyt vasta vain aloitussaldo muistetaan.

Käyttöesimerkki:

// tuttuun tapaan:
MuistavaTuotevarasto mehu = new MuistavaTuotevarasto("Juice", 1000.0, 1000.0);
mehu.otaVarastosta(11.3);
System.out.println(mehu.getNimi()); // Juice
mehu.lisaaVarastoon(1.0);
System.out.println(mehu);           // Juice: saldo = 989.7, vielä tilaa 10.3
...
// mutta vielä historia() ei toimi kunnolla:
System.out.println(mehu.historia()); // [1000.0]
   // saadaan siis vasta konstruktorin asettama historian alkupiste...
...

Tulostus siis:

Juice
Juice: saldo = 989.7, vielä tilaa 10.299999999999955
[1000.0]

MuistavaTuotevarasto, vaihe 2

On aika aloittaa historia! Ensimmäinen versio ei historiasta tiennyt kuin alkupisteen. Täydennä luokkaa metodein

Käyttöesimerkki:

// tuttuun tapaan:
MuistavaTuotevarasto mehu = new MuistavaTuotevarasto("Juice", 1000.0, 1000.0);
mehu.otaVarastosta(11.3);
System.out.println(mehu.getNimi()); // Juice
mehu.lisaaVarastoon(1.0);
System.out.println(mehu);           // Juice: saldo = 989.7, vielä tilaa 10.3
...
// mutta nyt on historiaakin:
System.out.println(mehu.historia()); // [1000.0, 988.7, 989.7]
...

Tulostus siis:

Juice
Juice: saldo = 989.7, vielä tilaa 10.299999999999955
[1000.0, 988.7, 989.7]

Muista miten korvaava metodi voi käyttää hyväkseen korvattua metodia!

MuistavaTuotevarasto, vaihe 3

Täydennä luokkaa metodilla

Käyttöesimerkki:

MuistavaTuotevarasto mehu = new MuistavaTuotevarasto("Juice", 1000.0, 1000.0);
mehu.otaVarastosta(11.3);
mehu.lisaaVarastoon(1.0);
//System.out.println(mehu.historia()); // [1000.0, 988.7, 989.7]

mehu.tulostaAnalyysi();

Metodi tulostaAnalyysi kirjoittaa ilmoituksen tyyliin:

Tuote: Juice
Historia: [1000.0, 988.7, 989.7]
Suurin tuotemäärä: 1000.0
Pienin tuotemäärä: 988.7
Keskiarvo: 992.8

MuistavaTuotevarasto, vaihe 4

Täydennä analyysin tulostus sellaiseksi, että mukana ovat myös muutoshistorian suurin muutos ja historian varianssi.

Laskin

Laskin

Tehtävässä on tarkoitus toteuttaa yksinkertainen laskin. Laskimen käyttöliittymän tulee olla seuraavanlainen:

Tehtäväpohjan mukana tulee käynnistyksen suorittava pääohjelma sekä graafisen käyttöliittymän sisältävä luokka GraafinenLaskin. Käyttöliittymän on oltava täsmälleen seuraavassa osassa kuvaillulla tavalla tehty, muuten saat vapaasti suunnitella ohjelman rakenteen.

Layout kuntoon

Käyttöliittymän pohjana olevassa JFramessa tulee käyttää asettelijana GridLayoutia jossa on kolme riviä ja yksi sarake. Ylimpänä on tuloskenttänä toimiva JTextField, jonka täytyy asettaa "pois päältä" metodikutsulla setEnabled(false). Toisena on syötekenttänä toimiva JTextField. Tuloskentässä on aluksi teksti 0 ja syötekenttä on tyhjä.

Alimpana komponenttina sijaitsee JPanel, jonka asettelijana on GridLayout, jossa on yksi rivi ja kolme saraketta. JPanelissa on kolme JButtonia, joissa tekstit "+", "-" ja "Z".

Laskimen käyttöliittymän koon on oltava vähintään 300*150.

Perustoiminnallisuus

Laskimen toimintalogiikka on seuraava. Käyttäjän kirjoittaessa syötekenttään luvun n ja painaessa +, lisätään tuloskentässä olevaan arvoon n ja päivitetään tuloskenttä uuteen arvoon. Vastaavasti käyttäjän kirjoittaessa syötekenttään luvun n ja painaessa -, vähennetään tuloskentässä olevasta arvosta n ja päivitetään tuloskenttä uuteen arvoon. Jos käyttäjä painaa Z, nollautuu tuloskenttä.

Vihje: joskus on tarkoituksenmukaista hoitaa yhdellä tapahtumankuuntelijalla usean napin painallusten käsittely. Tämä onnistuu kysymällä actionPerformed-metodin parametrilta kuka oli tapahtuman aiheuttaja. Seuraava koodi olettaa, että tapahtumankäsittelijällä on oliomuuttujat JButton plus ja JButton miinus jotka viittaavat plus- ja miinus-nappeihin:

    @Override
    public void actionPerformed(ActionEvent ae) {
        if (ae.getSource() == plus) {
           // käsittele plus-painike
        } else if (ae.getSource() == miinus) {
           // käsittele miinus-painike
        } else ...

Hienosäätö

Laajennetaan vielä ohjelmaa seuraavilla ominaisuuksilla: