Java-ohjelmointi, kesä 2001, Avoin yliopisto Koetehtävän 2 arvosteluperusteet Marja Huovinen Selityksissä ja painotuksissa on osin mukailtu syksyn 2000 (Antti Vähäkangas) ja syksyn 1999 (Jaakko Nurro) kokeiden arvostelua. Ensimmäisestä kohdasta sai maksimissaan 8 pistettä, kahdesta muusta kummastakin 6 pistettä. Ensimmäinen kohta ^^^^^^^^^^^^^^^^^ - Näkyvyysmääreet private ja public oikein selitetty 1.5p Private-näkyvyysmääreellä varustetut kentät / metodit ovat luokan sisäisiä eivätkä näy luokan ulkopuolelle (eivät edes luokan aliluokille). Public-näkyvyysmääreellä varustetut metodit / kentät ovat julkisia ja näkyvät kaikille ulkopuolisille luokille ts. näkyvyydelle ei ole asetettu mitään rajoituksia. - Näkyvyysmääreiden käyttö ja private-määreen hyödyt (kapselointi) selitetty/hyviä esimerkkejä 1.5p Kapseloinnin / abstraktin tietotyypin idea: voidaan erottaa olion sisäinen rakenne ja käyttörajapinta, jolloin luokan ilmentymää hyödyntävässä sovelluksessa käytetään julkisia työkaluja eikä olion sisäistä rakennetta ja sen toimintaa tarvitse tietää. Nämä julkiset välineet voidaan suunnitella siten, että operaatioilla ei voi saattaa oliota epämieluisaan tilaan. - static ja ei-static oikein selitetty 1.5p Static-määreellä varustettu metodi/muuttuja on luokkakohtainen eli luokan kaikki ilmentymät jakavat saman luokkamuuttujan. Ei-staattinen metodi/kenttä on ilmentymäkohtainen eli luokan ilmentymillä on omat kopiot kentistä. - selitykset/hyvät esimerkit staattisten ja ei-staattisten muuttujien/metodien käytöstä 1.5p Static-määreellä varustetun kentän/metodin käyttöön ei tarvita ilmentymää vaan niihin voidaan viitata luokan nimellä, esimerkiksi metodikutsussa tyyliin Luokka.metodi(). (kenttää voi käyttää myös ilmentymämetodin kautta). Staattiset metodit voivat käyttää vain staattisia kenttiä ja metodeita. Ei-staattiseen kenttään/metodiin voidaan viitata vain ilmentymän kautta, esimerkiksi metodikutsussa tyyliin olio.metodi(). Ilmentymäkohtaista kalustoa ei ole olemassa ennenkuin olio luodaan. - Näkyvyysmääreiden ja staticin/ei-staticin eri yhdistelmien selvitys (ks. "nelikenttä" Arto Wiklan www-materiaalissa, luku 4.2) 2p private static: Piilotetut luokkamuuttujat ja -metodit, esimerkiksi main-metodin tai kirjastometodin "pikku apulaiset". public static: Julkiset luokkamuuttujat ja -metodit, esimerkiksi main-metodi, kirjastoluokan metodit kuten Lue.kluku() ja Math.random() ja kirjastovakiot/luokkakohtaiset vakiot kuten Math.PI ja Integer.MIN_VALUE. private: Ilmentymien piilotetut rakenteet (joita voidaan käsitellä luokan ulkopuolelta aksessorien kautta) ja sisäiset apumetodit. public: Julkiset konstruktorit ja aksessorit. Ensimmäinen kohta oli yleisesti ottaen osattu hyvin. Kuitenkin useissa vastauksissa käsitteet oli määritelty huolellisesti, mutta varsinaiseen "miksi"-kysymykseen ei vastattu, eli perustelut näkyvyysmääreiden käytölle tai kuvaus staattisten ja ei-staattisten kenttien ja metodien käyttöeroista puuttuivat. Toinen kohta ^^^^^^^^^^^^ - Selitetty ilmentymän luominen luokasta L1 kun parametrin tyyppinä on abstrakti luokka 1p Parametriksi luokalle L1 on annettava abstraktin luokan T1 konkreettisen aliluokan ilmentymä. - Kuvailtu abstraktia luokkaa ja sen käyttötarkoituksia ("miksi"-kysymys) 2p Abstraktin luokan avulla voi luoda julkisen käyttörajapinnan, jolloin jonkin luokan käyttäjälle tarkoitettu kalusto määritellään erikseen abstraktissa luokassa ja toteutetaan konkreettisesti ei-abstraktissa aliluokassa, joka jää käyttäjältä piiloon. Vähemmän tarkka kuvaus tai hyvä esimerkki riitti, jos siitä selvästi huomasi kirjoittajan ymmärtäneen asian. - Selitetty ilmentymän luominen luokasta L1 kun parametrin tyyppinä on rajapintaluokka 1p Parametriksi luokalle L1 on annettava sellaisen luokan ilmentymä, joka toteuttaa (implements) rajapinnan T1. - Kuvailtu rajapintaluokkaa ja sen käyttötarkoituksia, mahdollisesti myös eroja abstraktiin luokkaan ("miksi"-kysymys) 2p Kuten abstrakti luokka, rajapintaluokka tarjoaa julkisen käyttörajapinnan, mutta kuitenkin erillisenä luokan perintähierarkiasta. (Jaakko Nurron sanoin: ) Rajapintaluokka antaa luokalle lisää tyyppimääreitä yliluokkien lisäksi, koska rajapinnan toteuttavaa luokkaa voidaan käyttää rajapintaluokan ilmentymänä. Täten saadaan joidenkin kielten moniperinnän polymorfismiominaisuudet käyttöön, mutta ei tule ongelmia päällekkäin periytyvästä aineksesta. Rajapintaluokkaa voidaan siis käyttää yhdistämään luokkia, jotka eivät ole saman luokan aliluokkia. Maininnat "listasta, joka kertoo mitä metodeita on toteutettava" abstraktin luokan tai rajapintaluokan yhteydessä eivät riittäneet selityspisteiden saamiseen. Moniperinnän mainitseminen ei ollut välttämätöntä täysien pisteiden saamiseen tästä kohdasta, jos oli muuten hyvä selitys. Hyvät esimerkit kelpasivat tässäkin. Moni ei hahmottanut tehtävänannosta, että on erillisen aliluokan tai rajapinnan toteuttavan luokan avulla luotava olio tyyppiä T1, joka annetaan parametriksi luokan L1 konstruktorille. Sen sijaan yritettiin vääntää luokasta L1 abstraktin luokan aliluokkaa tai rajapinnan toteuttavaa luokkaa. Useat käyttivät myös ilmaisua "annetaan parametriksi luokka, joka toteuttaa rajapinnan..." tms. vaikka kyse on nimenomaan sellaisen luokan ilmentymästä. Tästä vähensin puolikkaan, jos ilmentymää ei mainittu selvästi missään osassa selitystä. Monessa vastauksessa selitettiin rajapintaluokan yhdistävän joitain tiettyjä aliluokkia, vaikka mitkä tahansa luokat voivat toteuttaa rajapinnan perimishierarkiasta riippumatta. Ilmeisesti eläinesimerkki, jossa rajapinnan toteuttavat luokat kuuluivat samaan luokkahierarkiaan, johti harhaan jos ei tutustunut muihin esimerkkeihin/kuvauksiin. Kolmas kohta ^^^^^^^^^^^^ - Selitetty, miten saa yhden halutun version luokasta L1 käyttöön 3p Samassa pakkauksessa oleva luokka on oletusarvoisesti käytössä. Pakkauksessa "omapakkaus" oleva versio saadaan käyttöön samassa pakkauksessa olevan sijasta eksplisiittisellä importoinnilla: "import omapakkaus.L3;" Samoin "java.lang"-pakkauksessa oleva versio on tuotava käyttöön eksplisiittisesti: "import java.lang.L3;" Pakkauksessa java.lang oleva luokka on oletusarvoisesti käytössä vain, jos käännösyksikön omassa pakkauksessa ei ole samannimistä luokkaa. - Selitetty, miten voi käyttää useita luokan versioita samassa käännösyksikössä 3p Ainoa tapa saada useita samannimisiä luokkia käyttöön samassa käännösyksikössä on viitata luokkiin niiden koko nimellä eli pakkaus.luokka. Importilla voi sitten määritellä, mihin versioon halutaan viitata pelkällä luokan nimellä. Oletusarvoisesti (ilman eksplisiittistä importointia) pelkällä luokan nimellä viitatessa viitataan samassa pakkauksessa olevaan luokkaan. Pakkauksessa "omapakkaus" olevaan luokkaan L3 viitataan tällöin nimellä "omapakkaus.L3" ja pakkauksessa "java.lang" olevaan versioon "java.lang.L3". Useamman samannimisen luokan eksplisiittinen käyttöön tuominen (import pakkaus.luokka) samassa käännösyksikössä, jolloin siis yritettäisiin viitata pelkällä luokan nimellä useampaan luokkaan, aiheuttaa käännösaikaisen virheen, koska käännösyksikössä voidaan yhdellä nimellä viitata vain yhteen luokkaan kerrallaan. Tämän takia on käytettävä pakkausnimiä samannimisten luokkien erottamiseen. Implisiittinen tuonti "import pakkaus.*" ei ollut tässä tehtävässä erityisen hyödyllinen, koska käännösyksikön pakkauksessa oleva versio luokasta L3 asettuu implisiittisesti importoidun edelle. Nimien etsintäjärjestyksen kuvailu yleensä selvensi vastausta, mutta ei ollut välttämätön täysiin pisteisiin. Tämä osa tehtävää tuotti vastaajille selvästi eniten hankaluuksia. Importoinnit yleensä osattiin selittää, muttei välttämättä sitä, miten saadaan käyttöön useita versioita yhtä aikaa käyttämällä koko nimiä. Implisiittisen ja eksplisiittisen importin ero ("*" vs. "luokannimi") oli monelle hiukan hämärän peitossa, jolloin yritettiin käyttää implisiittistä eksplisiittisen tavoin. Samaten moni arveli, että java.langissa oleva versio on oletusarvoisesti käytössä, koska java.lang-pakkausta ei tarvitse erikseen importoida. Kuitenkin luokan nimellä on käytössä oletusarvoisesti samassa pakkauksessa oleva luokka ja java.langissa oleva vasta toissijaisesti (ilman tilannetta muuttavia tuontikäskyjä). _________ Max 8 + 6 + 6 = 20 pistettä Keskiarvo oli n. 11,5 pistettä