Date: Thu, 16 Jan 2003 09:00:24 +0200 (EET) From: Hannu J Raisanen Tehtävä arvosteltiin vähentävällä systeemillä, siis erilaiset virheet pisteytettiin ja vähennettiin maksimipistemäärästä (18 pistettä). Mikäli saavutetut pisteet laskivat tällä systeemillä alle kuuteen pisteeseen, alettiin vastauksesta etsiä ansioita, joiden perusteella opiskelija saavutti 0-5 pistettä. Vähennykset tehtävään 2a: ----------------------- a) privaatti koodikenttä ei final : -0p Tätä vähennystä ei loppujen lopuksi tehty, vaan katsottiin, että koska luokassa ei ole aksessoreja arvon muuttamiseen, suojaus on riittävä. b) laskuri ei static : -2p Jos koodeja laskeva laskuri ei ole static, yksittäisten tarinoiden koodit eivät saa oikeita arvoja. Luokka- ja oliomuuttujien eron ymmärtäminen on Javassa olennaista. c) koodikenttä ei saa oikeita arvoja : -1p Satunnaiset ohjelmointivirheet, jotka aiheuttavat laskurin toiminnan epäonnistumisen. Ensimmäisellä arvolla ei ole merkitystä. d) koodikenttä ja laskuri sama muuttuja : -4p (jos tällainen vähennys, niin yo. vähennyksiä ei laskettu) Tällainen menettely aiheuttaa laskurin toiminnan täydellisen toimimattomuuden. e) muuttujien näkyvyys ei private : -2p Tehtävänannossa erikseen käskettiin muuttujat privaateiksi. Protectediksi muuttaminen oli virhe, sillä se ei ollut millään tapaa välttämätöntä b-kohdan tekemiselle. f) väärin määritellyt muuttujat metodeissa, : -2p myös pelkästään esitellyn taulukon käyttäminen Tyypillinen virhe oli viittaaminen itse esiteltyyn taulukkomuuttujaan, jota ei oltu ikinä luotu. g) stringitaulukosta ei tehdä konstruktorissa aitoa kopiota : -2p Tehtävänannossa käskettiin estää Tarinan muuttaminen. Jos konstruktorin parametrina saama taulukko sijoitetaan suoraan muuttujaan, niin sen sisältöä voidaan edelleen muuttaa riippumatta siitä, onko taulukko määritelty final-avainsanalla. Sama vähennys tehtiin mikäli opiskelija kirjoitti luokkaan metodin, joka palauttaa suoran viittauksen privaattiin tarinataulukkoon. Tämä oli tehtävän yleisin virhe, se löytyi yli 50% papereista. h) mikaOnTarinanRivi(...)-metodissa ei varauduta vuotoihin : -2p Tehtävänannossa käsketään varautua virheisiin. Tämä oli loppujen lopuksi ainoa virhetyyppi, johon tarvitsi varautua. Esim. parametrien null-arvot eivät aiheuttaneet pisteiden vähennyksiä. i) koosta-metodi ei palauta uutta tarinaa, : max -4p muutellaan omaa taulukkoa, metodi toimii väärin j) indeksivirheet koosta(...)-metodissa : -2p Yhden rivin heitot eivät aiheuttaneet vähennyksiä, sen sijaan koko Tarinan pituinen heitto arvosssa aiheutti tämän pistevähennyksen. k) satunnaiset ohjelmointivirheet : -1p Ne satunnaiset ohjelmointivirheet, jotka kuitenkin voidaan aidoiksi virheiksi laskea, ei esim. sulun puuttuminen. Vähennykset tehtävään 2b: ----------------------- a) "extends Tarina" puuttuu : -2p Tätä virhettä ei löytynyt kuin parista paperista. Kyse on luultavasti huolimattomuudesta, mutta virheenä niin paha, että tästä sakotettiin. b) Tarina-luokan rakenteiden toistaminen : -4p Tarinan tietorakenteita ei ole mitään syytä toistaa. Myös tarinan privaattikentät ovat periytyneet, niihin ei vain pääse käsiksi edes aliluokassa kuin julkisten aksessoreiden kautta. c) konstruktori puuttuu : -3p Konstruktori ei periydy. d) super(...)-kutsu puuttuu, jos konstruktori oli : -2p Ne rakenteet, joihin ei itse päästä käsiksi, alustetaan yliluokan konstruktorin kutsulla. e) yli- ja alivuotoihin ei varauduttu eri metodeissa : -2p f) tulostaKommentit()-metodissa tulostetaan : -2p null-kommenttirivit Tehtävänannossa käsketään tulostaa ei-tyhjät kommenttirivit. h) viittauksia Tarinan private-kenttiin : -3p Kaikkiin Tarinan privaattikenttiin tulee viitata aksessoreiden avulla. i) koosta-metodi ei toimi oikein : max -4p j) satunnaiset ohjelmointivirheet : -1p Arvostelussa ei ole tehty 2a-tehtävän kanssa toisteisia vähennyksiä. Esimerkkivastaukset: public class Tarina { private static int koodiLaskuri = 0; private final int koodi; private String[] tarina; public Tarina(String[] rivit) { koodiLaskuri++; koodi = koodiLaskuri; tarina = new String[rivit.length]; for (int i=0; i= 0 && rivi < mikäOnTarinanPituus()) { return tarina[rivi]; } return null; } public void tulostaTarina() { for (int i=0; i < mikäOnTarinanPituus(); i++) { System.out.println("(" + i + ".) " + mikäOnTarinanRivi(i)); } } public Tarina koosta(Tarina toinen) { int uudenPituus = mikäOnTarinanPituus() + toinen.mikäOnTarinanPituus(); String[] koottuTarina = new String[uudenPituus]; for (int i=0; i < mikäOnTarinanPituus(); i++) { koottuTarina[i] = mikäOnTarinanRivi(i); } for (int i=0; i< toinen.mikäOnTarinanPituus(); i++) { koottuTarina[i + mikäOnTarinanPituus()] = // Kumpi tahansa seuraavista toimii, // ensimmäinen on suositeltavampi. toinen.mikäOnTarinanRivi(i); //toinen.tarina[i]; } return new Tarina(koottuTarina); } } public class KommentoituTarina extends Tarina { private String[] kommentit; public KommentoituTarina(String[] rivit) { super(rivit); kommentit = new String[rivit.length]; } public void liitäKommentti(String kommentti, int rivi) { if (rivi >= 0 && rivi < mikäOnTarinanPituus()) { kommentit[rivi] = kommentti; } } public String mikäOnKommentti(int rivi) { if (rivi >= 0 && rivi < mikäOnTarinanPituus()) { return kommentit[rivi]; } return null; } public void tulostaKommentit() { for (int i=0; i < mikäOnTarinanPituus(); i++) { if (kommentit[i] != null) { System.out.println("(" + i + ".) " + kommentit[i]); } } } public KommentoituTarina koosta(KommentoituTarina toinen) { int uudenPituus = mikäOnTarinanPituus() + toinen.mikäOnTarinanPituus(); String[] koottuTarina = new String[uudenPituus]; for (int i=0; i < mikäOnTarinanPituus(); i++) { koottuTarina[i] = mikäOnTarinanRivi(i); } for (int i=0; i< toinen.mikäOnTarinanPituus(); i++) { koottuTarina[i + mikäOnTarinanPituus()] = toinen.mikäOnTarinanRivi(i); } KommentoituTarina uusiTarina = new KommentoituTarina( koottuTarina); for (int i=0; i < mikäOnTarinanPituus(); i++) { uusiTarina.liitäKommentti(mikäOnKommentti(i),i); } for (int i=0; i< toinen.mikäOnTarinanPituus(); i++) { uusiTarina.liitäKommentti( toinen.mikäOnKommentti(i), i + mikäOnTarinanPituus()); } return uusiTarina; } }