Java-ohjelmoinnin kurssikoe 18.12.2001 Tehtävä 2, arvostelija Jussi Kollin (jussi.kollin@helsinki.fi) Tehtävän algoritminen sisältö oli varsin heppoinen, joten arvostelu painottui vakioihin ja luokkamuuttujiin (A-kohta) sekä luokkien periyttämiseen (B-kohta). Jos vastatessa oli tehnyt virheitä, jotka olisi pitänyt jo Ohjelmoinnin perusteet-kurssilla osata, niin näistä myös sakotettiin varsin ankarasti. Selityksillä, joista kävi ilmi että tiedettiin mitä piti jonkin rivin piti tehdä (riittävän yksityiskohtaisesti) ja miksi sen piti tehdä niin, sai parhaimmillaan 2p edestä anteeksi. Kummastakin kohdasta saattoi saada max 7p. A) Kentät: ------- Tehtävänannossa painotettiin, ettei basiliskon "henkilötunnusta" voida muuttaa konstruktorin jälkeen, siis tämän kentän oli oltava vakio (final-määre kentän edessä). Kentän määrittelyn yhteydessä vakiolle ei saanut antaa vakioarvoa (esim. 0). Vakio ei voinut saada omaa arvoaan ilman luokkamuuttujaa, joka piti kirjaa luoduista olioista. Tähän tarvittiin siis 'static'-määreellä varustettu laskuri, jota kasvatettiin *vain yhdessä konstruktorissa*. Tehtävänannossa käskettiin asettaa kaikkien kenttien näkyvyydeksi 'private'. Tämä ei ollut virhe, kuten jotkut luulivat. Toisin tekemi- sestä sakotettiin. Metodit: -------- Tehtävässä kaivattiin yhtä konstruktoria. Jos useampia oltiin tehty, en ottanut pisteitä. Tällöin kuitenkin oli huolehdittava että jokai- sessa kasvatettiin laskuria. Edelleenkään toString() ei sisällä System.out.println()-lausetta. Tämä oli osapuilleen ainoa virhe, joka tässä tehtävässä oli tehty, poislukien mystinen merkintä " .. + this.Basilisko". Pariudu-metodi EI ole konstruktori. Liian monet olivat toteuttaneet sen näin: public Basilisko pariudu (Basilisko toinen) { if (Math.random() < 0.5) this.perimä = perimä; else this.perimä = toinen.perimä; } Toinen yleinen virhe: public Basilisko pariudu (Basilisko toinen) { if (Math.random() < .5) Basilisko lapsi = new Basilisko(basilisko.perima); else Basilisko lapsi = new Basilisko(this.perima); return lapsi; } Metodin siis on palautettava uusi (new-operaattorilla luotu) olio, joka on konstruktorissa saanut parametrina joko this.perimä:n tai toinen.perimä:n. Metodissa mikäOnPerimä() ei tehty virheitä. Pisteytys: --------- * yksilöllisyyskenttä ei final : -2p * laskuri ei static : -2p * yksilöllisyyskenttä ei saa oikeita arvoja : -1p * yksilöllisyyskenttä ja laskuri sama muuttuja : -4p (jos tällainen vähennys, niin yo. final/static-vähennyksiä ei laskettu) * muuttujien näkyvyys ei private : -2p * väärin määritellyt muuttujat metodeissa : -2p * pariudu-metodi: * ei osattu luoda oliota tai muuteltiin omia kenttiä : -4p * kaksi erillistä if-lausetta, joissa molemmissa Math.random() : -2p * toString: * System.out.println() kummitteli metodissa : -2p B) Kentät: ------- Uusia kenttiä ei pitänyt olla. Metodit: -------- Tarvittiin välttämättä konstruktori, joka oli muotoa: public TuplaBasilisko (String perimä) { super(perimä); } Tässä monet tekivät virheen. Seuraavat kaksi esimerkkiä toimivat samalla tavalla väärin: public TuplaBasilisko (String perimä) { } public TuplaBasilisko (String perimä) { super(); } Ensinnäkin, konstruktorit EIVÄT PERIYDY. Toiseksi, pelkkä super() ei riitä, jollei Basiliskossa määritelty erikseen parametritonta konstruktoria. Toinen metodi, joka luokassa oli oltava, oli "pariudu". Tässä moni lankesi luulemaan, että private-määre tarkoittaa olion sisäistä näkyvyyttä. Koska private tarkoittaa kuitenkin vain luokan sisäistä näkyvyyttä, niin pariudu-metodissa oli pakko käyttää aksessoreja yliluokan kenttien näkemiseen, tarkemmin sanoen metodia mikäOnPerimä(). Siis oli ehdottoman väärin käyttää merkintää "this.perimä" tai "toinen.perimä" perimien katenoinnin yhteydessä. Toinen huomautuksen aihe on että tässä metodissa kaksi Tupla- Basiliskoa pariutuvat. Eräät tekivät tästä metodista sellaisen, joka palautti uuden Basiliskon, jonka perimä oli määräytynyt kuten TuplaBasiliskoilla. Tätä voisi verrata siihen, että ihmisten lapset ovat nisäkkäitä mutta eivät ihmisiä. Pisteytys: ---------- * "extends Basilisko" puuttuu: : -4p * konstruktorit * TuplaBasilisko: * ei konstruktoria : -3p * ei super(perimä)-kutsua jos konstruktori oli : -2p * pariudu-metodi * metodin otsake: public TuplaBasilisko pariudu(Basilisko basilisko) : -2p (kuormituksen säännöt!) * ei toimi oikein : -2p * samoja virheitä kuin Basiliskon metodeissa; kuitenkaan saman virheen toistamisesta ei tullut lisämiinuksia. * ei viittauksia TuplaBasiliskosta Basiliskon private- kenttiin : -3p * muut virheet vähennyksiä yhdestä neljään pistettä vakavuuden mukaan. ESIMERKKIRATKAISU kommentteineen: A) public class Basilisko { private final int hetu; private String perima; private static int idLaskuri = 0; public Basilisko(String perima) { idLaskuri++; // Ensimmäinen olio saa hetuksi ykkösen hetu = idLaskuri; this.perima = perima; } public Basilisko pariudu(Basilisko basilisko) { String lapsenPerimä; if (Math.random() < .5) lapsenPerimä = basilisko.perima; else lapsenPerimä = this.perima; return new Basilisko(lapsenPerimä); } public String mikäOnPerimä() { return perima; } public String toString() { return "(" + hetu + "): " + perima; } } B) public class TuplaBasilisko extends Basilisko { public TuplaBasilisko(String perima) { super(perima); } public TuplaBasilisko pariudu(TuplaBasilisko toinen) { String lapsenPerimä = this.mikäOnPerimä() + toinen.mikäOnPerimä(); TuplaBasilisko lapsi = new TuplaBasilisko(lapsenPerimä); return lapsi; } } Jakauma: 1 14 ************** 2 3 *** 3 7 ******* 4 15 *************** 5 9 ********* 6 15 *************** 7 12 ************ 8 21 ********************* 9 32 ******************************** 10 15 *************** 11 25 ************************* 12 26 ************************** 13 19 ******************* 14 14 ************** Vastanneita 238, joiden keskiarvo 8.2 pistettä