Mikäli kaipaat apuja NetBeanssin käytön aloittamiseen tutustu seuraaviin linkeihin: NetBeans aloitusohje. Valitse kuitenkin kurssiksi XXX-ohja-kertaus
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
Tee luokka Tavara
, josta muodostetut oliot vastaavat erilaisia tavaroita. Tallennettavat tiedot ovat tavaran nimi ja paino (kg).
Lisää luokkaan seuraavat metodit:
public String getNimi()
, joka palauttaa tavaran nimenpublic int getPaino()
, joka palauttaa tavaran painonpublic String toString()
, joka palauttaa merkkijonon muotoa "nimi (paino kg)"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)
Tee luokka Matkalaukku
. Matkalaukkuun liittyy tavaroita ja maksimipaino, joka määrittelee tavaroiden suurimman mahdollisen yhteispainon.
Lisää luokkaan seuraavat metodit:
public void lisaaTavara(Tavara tavara)
, joka lisää parametrina annettavan tavaran matkalaukkuun. Metodi ei palauta mitään arvoa.public String toString()
, joka palauttaa merkkijonon muotoa "x tavaraa (y kg)"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)
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)
Lisää luokkaan Matkalaukku
seuraavat metodit:
tulostaTavarat
, joka tulostaa kaikki matkalaukussa olevat tavaratyhteispaino
, joka palauttaa tavaroiden yhteispainonSeuraavassa 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.
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)
Tee luokka Lastiruuma
, johon liittyvät seuraavat metodit:
public void lisaaMatkalaukku(Matkalaukku laukku)
, joka lisää parametrina annetun matkalaukun lastiruumaanpublic String toString()
, joka palauttaa merkkijonon muotoa "x matkalaukkua (y kg)"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)
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)
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
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
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.
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ä.
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?
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
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
.
Luo pakkaukseen siirrettava
luokka Elio
, joka toteuttaa rajapinnan Siirrettava
. Eliön tulee tietää oma sijaintinsa (x, y -koordinaatteina). Luokan Elio
APIn tulee olla seuraava:
"x: 3; y: 6"
. Huomaa että koordinaatit on erotettu puolipisteellä (;
)dx
sisältää muutoksen koordinaattiin x
, muuttuja dy
sisältää muutoksen koordinaattiin y
. Esimerkiksi jos muuttujan dx
arvo on 5, tulee oliomuuttujan x
arvoa kasvattaa viidellä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
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.
Siirrettava
-rajapinnan toteuttavan olionKokeile 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
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 }
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
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
.
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!
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
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.
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!
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
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
.
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
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ä toString
iä.
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
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
-olion.
Täydennä Muutoshistoria
-luokkaa analyysimetodein:
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.)
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]
On aika aloittaa historia! Ensimmäinen versio ei historiasta tiennyt kuin alkupisteen. Täydennä luokkaa metodein
Varasto
-luokan metodi, mutta muuttunut tilanne kirjataan historiaan. Huom: historiaan tulee kirjata poiston jälkeinen varastosaldo, ei poistettavaa määrää!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!
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
Täydennä analyysin tulostus sellaiseksi, että mukana ovat myös muutoshistorian suurin muutos ja historian varianssi.
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.
Käyttöliittymän pohjana olevassa JFrame
ssa tulee käyttää asettelijana GridLayout
ia 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 JButton
ia, joissa tekstit "+", "-" ja "Z".
Laskimen käyttöliittymän koon on oltava vähintään 300*150.
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 ...
Laajennetaan vielä ohjelmaa seuraavilla ominaisuuksilla:
setEnabled(false)
. Muissa tilanteissa napin tulee olla päällä.