tehtävä 1 7 pistettä (ML) ========================== 1 piste/kohta periytyminen ------------ http://www.cs.helsinki.fi/group/java/k10/ohja/materiaali3.html#periytyminen Luokka A voi periä jonkun luokan B, jolloin luokan B metodit ja attribuutit (joiden näkyvyysmääre ei ole private) tulevat myäs luokalle B. Myäs private-näkyvyyden attribuutit periytyvät, mutta eivät näy suoraan luokassa A. Koodissa: class A { // ... } class B extends A { // ... } yliluokka ja aliluokka ---------------------- Perivä luokka A on aliluokka ja perittävä B on yliluokka. abstrakti luokka ---------------- http://www.cs.helsinki.fi/group/java/k10/ohja/materiaali4.html#abstrakti_luokka Luokka josta ei voi luoda olioita. Voi sisältää abstraketja metodeja jotka määrittelevät ainoastaan metodin nimen ja tyypin. Abstrakti luokka voidaan periä. Jotta perivästä luokasta voitaisiin luoda olioita, on siinä toteutettava abstraktit metodit. abstract class Ab { // ... abstract int metodi(); } class Aa extends Ab { int metodi(){ return 0; } } rajapinta -------- http://www.cs.helsinki.fi/group/java/k10/ohja/materiaali2.html#rajapinta Määritelmä metodeista, jotka rajapinnan toteuttavan luokan on pakko toteuttaa. interface R { int metodi(); } A implements R { int metodi(){ return 0; } } polymorfismi ----------- Olio voi edustaa "montaa eri tyyppiä", esim: interface Ajettava { void aja(); } class Auto implements Ajettava { void tankkaa(int x){ ... } void aja(){ ... } void avaaOvi(){ ... } ... } class LinjaAuto extends Auto { ... int matkustajaLukumaara() { ... } void avaaOvi( ... ) } Oletetaan että on luotu LinjaAuto: la = new LinjaAuto(); viitettä la voidaan käsitellä tyypeissä: Object Ajettava Auto LinjaAuto Esim. la voidaan antaa parametriksi Ajettava-tyyppistä parametria odottavalle metodille. Kun la:ta käsitellään Ajettavana, voidaan kuitenkin kutsua ainoastaan sen Ajettava-rajapinnassa kutsuttuja metodeja, ei esim. metodia avaaOvi() Jos la:ta käsitellään Auto-tyyppisenä, ja kutsutaan sen metodia avaaOvi() tulee automaattisesti kutsutuksi la:n "oikeassa tyypissä" eli LinjaAuto:ssa määritelty metoditoteutus. Samoin on mm. metodin toString-suhteen. Luokka Object määrittelee oletusarvoisen toString:in kuitenkin aina kun olio tulostetaan, riippumatta minkä tyyppisenä sitä kutsutaan, tulee aina kutsutuksi olion oikean tyypin mukainen toteutus toStringistä. static ------ http://www.cs.helsinki.fi/group/java/k10/ohja/materiaali1.html#stat_ja_ei kapselointi ----------- http://www.cs.helsinki.fi/group/java/k10/ohja/materiaali1.html#kap Suppeassa mielessä: Luokan rakenteen piilottaminen, esim. tekemällä attribuuteista privateja ja luomalla niille tarvittaessa getterit ja setterit. tehtävä 2 11 pistettä (ML) =========================== Valmiina luokka abstrrakti Kuvio: public Kuvio(int x, int y) luo kuvio-olion ja asettaa sen x ja y koordinaatit parametrina saaduiksi koordinaateiksi. public int getX() palauttaa kuvioon liittyvän x-koordinaatin. public void setX(int x) asettaa kuvioon liittyvän x-koordinaatin. public int getY() palauttaa kuvioon liittyvän y-koordinaatin. public void setY(int y) asettaa kuvioon liittyvän y-koordinaatin. public abstract double pintaAla() palauttaa kuvion pinta-alan. public class Nelio extends Kuvio { private sivu; public Nelio(int x, int y, int sivunPituus) { super(x,y); sivu = sivunPistuus; } public int getSivunPituus() { return sivu; } public void siirraKohtaan(int uusiX, int uusiY){ setX(uusiX); setY(uusiY); } public double pintaAla(){ return sivu*sivu; } } public class Ympyra extends Kuvio { double sade; public Ympyra(int x, int y, double sade) { super(x,y); this.sade = sade; } public double getSade() { return sade; } public void setSade(double sade) { this.sade = sade; } public double pintaAla(){ return sade*sade*Math.PI; } pisteytys: * perimisen syntaksi oikein 1p * luokan muu rakenne kunnossa 1p * konstruktorit oikein 2p * abstrakti metodi ylikirjoitettu 2p * normaalit metodit oikein 4p (1p/metodi) * johdonmukaisuus näkyvyyksissä 1p Tehtävä 3 ========= Kokeista löytyneitä pulmia. Jos ongelmat on huomioitu kommentilla koodissa, tai kirjoitettu ylös suunnitteluvaiheeseen, pisterokotukset pienenevät. Pisteiden rokotus riippuu myös yleisesti ohjelman rakenteesta, jos ohjelman rakenne on suunniteltu loogiseksi kokonaisuudeksi, ja esimerkiksi viitteissä on ongelmia (jotka esim. IDE huomaisi heti), pisterokotukset myös pienenevät. Rakenteesta * Selitys puuttuu -> -2-x p * Ei ollenkaan toteutusta, pelkkä selitys -> -8-x p * Koko ohjelma saman metodin sisällä (Huonoa ohjelmointityyliä) -> -4p * Koko ohjelma saman luokan sisällä (Vastuun jaon puuttuminen) -> -1-x p (riippuu rakenteesta ja ohjelman vastuunjaosta) * Loppumaton toisto, joka estää muistion toiminnan, esim -> -4p while(oluet.get(nimi) != null) { System.out.println(oluet.get(nimi)); } Viittauksista * Viittaus staattisesta kontekstista ei staattiseen kontekstiin, esim -> -2-x p public static void main(...) { teeJotain(); } public void teeJotain() { ... } tai; class Kala { private int pituus; public static void tulostaPituus() { System.out.println(pituus); } } * Viittaus metodissa muuttujaan, jota ei ole näkyvissä; esim: -> -2-x p (riippuu rakenteesta muuten) public static void main(...) { int kissa = 4; tulostaKissa(); } public static void tulostaKissa() { System.out.println(kissa); } * Viittaus muuttujaan jota ei ole (lohkossa olevat muuttujathan pysyvät lohkossa), esim: -> -2p if(kissa) { String nimi = "Jee!"; } else { String nimi = "Noo!"; } System.out.println(nimi); Koodin luettavuudesta, suunnittelusta ja rakenteesta * Tyhjä if-lohko, esim: -> -1p if(kissa) { } else { teeJotain(); } * Metodin paluuarvot puuttuu, esim: -> -2p public tulostaKissa() { // void puuttuu! System.out.println("kissa"); } * Metodien vastuu ja nimeäminen, metodi tekee muuta kuin sen nimestä olettaa. public String tulostaKissat() { -> -1p System.out.println("Anna kissan nimi: "); String kissanNimi = lukija.nextLine(); System.out.println("Kiitos!"); return kissanNimi; } * Sama koodi toistuu useassa paikassa, esimerkki ei nyt niin paha..: -> -1p if(oluet.contains(olut)) { tulostaOluet(); return; } oluet.add(olut); tulostaOluet(); -> kannattaisi olla esim: if(!oluet.contains(olut)) { oluet.add(olut); } tulostaOluet(); Olutmuistiosta * Ei ArrayList-luonteja oluita muistioon lisättäessä, johtaa NullPointerExceptioniin -> -3p * Voi tallettaa vain yhden oluen, esim -> -4p HashMap nimenOluet = new HashMap(); tai oikein rakennettu HashMap, mutta olutlistan uudelleen alustus joka juonnilla. * Ei käytetä indeksiä oluen tunnistamiseen -> -2p * Ei Nimi -> Nimelle kuuluvat oluet rakennetta (HashMap tai vastaava) -> -4p * Indeksin tulostus siten, että jokainen olut samassa indeksissä. -> -2p Metodeista * Metodikutsussa annettu parametrin tyyppi, esim: -> -0,5p public static void main(...) { String kissa = "mow"; tulostaKissa(String kissa); } * Metodimäärittelyssä operaatio, esim: -> -1 p public void tulostaNumero(int luku -5) { System.out.println(luku); } ArrayListista, Scannerista, Poikkeuksista ym. * Scannerin käyttö siten, että seuraavalla kierroksella tulee ongelmia -> -1p while (true) { String nimi = lukija.nextLine(); int arvo = lukija.nextInt(); ... } toisella kierroksella nimeä ei lueta, sillä nextInt()-metodi ei syö rivinvaihtomerkkiä * Ei indeksitarkastuksia (esim, onko syötetty arvo listalla) -> -0,5p * ArrayListin tai HashMapin tyyppi puuttuu, esim: -> -0,5p ArrayList oluet = new ArrayList(); * Ei tarkisteta poikkeusta jos käytössä Integer.parseInt(lukija.nextLine()) -> -0,5p * Muuttujien alustus useaan kertaan; -> ei miinusta public class Kissa { private String nimi = "Miuku!" public Kissa(String nimi) { this.nimi = nimi; } ... } * ArrayListin koon tarkistus jollain tavalla "väärin" -> -0,5p * ArrayListin indeksointi taulukkona, esim: -> -2p ArrayList oluet = new ArrayList(); oluet.add("ABC"); System.out.println(oluet[0]);