Tämä kurssi on jo päättynyt.

Kurssin viimeisimmän version löydät täältä: O1: 2024

Luku 3.2: Rajapintoja ja dokumentteja

Tästä sivusta:

Pääkysymyksiä: Mistä saan selville, miten jotain valmista luokkaa käytetään? Miten autan luokkani käyttäjää käyttämään sitä oikein? Miten ilmoitan, että muuttuja on tarkoitettu vain luokan sisäiseen käyttöön?

Mitä käsitellään? Julkinen vs. yksityinen; rajapinta vs. toteutus; tiedon piilottaminen. Scaladoc-dokumentaatio; Scala API ja sen dokumentaatio.

Mitä tehdään? Lähinnä luetaan.

Suuntaa antava työläysarvio:? Pari tuntia.

Pistearvo: A10.

Oheisprojektit: Oliointro, FlappyBug.

../_images/sound_icon1.png

Muuta: Luku sisältää lyhyen videon, joka esittelee luvun aihetta. Kuulokkeista tai kaiuttimista on siksi hyötyä.

../_images/person05.png

Johdanto: olioiden rajapinnat

Luvuissa 1.6 ja 2.1 on jo puhuttu abstraktioista ja siitä, miten oliolla on "julkisivu". Julkisivu on abstraktio, jonka kautta oliota käytetään. Palataan nyt aiheeseen ja otetaan samalla käyttöön muutama termi.

Yksityinen vs. julkinen

Osa olioiden piirteistä on julkisia (public). Tämä tarkoittaa sitä, että näitä piirteitä voi käyttää mistä tahansa muualta ohjelmasta. Esimerkiksi kurssioliolla voi olla julkinen metodi ilmoitaOpiskelija, jota voi kutsua jokin toisenlainen olio. Olioille viestitään juuri niiden julkisiksi määriteltyjä piirteitä hyödyntämällä.

Olioilla on myös yksityisiä (private) osia. Yksityistä on se, miten tietynlaiset oliot sisäisesti toimivat. Esimerkiksi yksityiskohdat siitä, mitä kurssiolio tekee ilmoittaakseen opiskelijan kurssille, on tämäntyyppisten olioiden yksityisasia. Samoin vaikkapa se, miten luvussa 2.1 käytetty papukaijaolio valitsi vastauksen vastaa-metodia kutsuttaessa oli tuon olion yksityinen piirre.

Rajapinta vs. toteutus

Olion julkiset piirteet määrittelevät sen rajapinnan (interface). Yksityiset piirteet puolestaan muodostavat toteutuksen (implementation), jonka varassa rajapinta toimii.

Vastaavasti voimme puhua luokan rajapinnasta ja toteutuksesta: luokkamäärittelyhän kuvaa etukäteen kerralla, mitä tietynlaisten olioiden rajapintaan ja toteutukseen kuuluu.

Seuraava video tarinoi lyhyesti siitä, miksi rajapinta on hyvä erottaa toteutuksesta.

Luokan tai olion käyttäjän tulee siis tuntea sen rajapinta. Toteutusta taas ei normaalitilanteessa tarvitse tuntea. Tilannetta voi verrata muuhun teknologiaan: Mitä television käyttäjän tulee tietää televisiosta käyttääkseen sitä? Mikä on television "rajapinta"? Haluaako edes televisiotekniikan ammattilainen pitää mielessä laitteen sisäisen toiminnan yksityiskohtia sohvalla kanavaa vaihtaessaan?

Kuten television tai auton tapauksessakin, myös ohjelmoidessa toteutustekniikan tuntemus voi auttaa toimintavikojen ratkomisessa, mutta yleensä toteutusta ei tarvitse pitää mielessä. Jopa sen henkilön, joka on tietyn ohjelmakomponentin toteuttanut, on usein eduksi väliaikaisesti "unohtaa" komponentin yksityiset osat, jotta hän voi keskittyä käyttämään komponenttia laajemman kokonaisuuden osana.

Jotta laajan ohjelmakokonaisuuden tai muun järjestelmän laatiminen olisi ylipäänsä mahdollista, tarvitaan useita tekijöitä, joista kukin on perehtynyt tiettyjen komponenttien toteutukseen muttei kaikkien. Kunkin tekijän tulee kuitenkin tuntea ne rajapinnat, joiden avulla hänen vastuullaan oleva komponentti voidaan yhdistää toisiin komponentteihin.

Rajapinnan erottaminen toteutuksesta on ohjelmoinnissa ja tekniikassa yleisemminkin aivan keskeinen ajatus. Ohjelmoinnin yhteydessä siitä käytetään usein termiä tiedon piilottaminen (information hiding): ohjelman osan (kuten olion) toteutuksen yksityiskohdat ikään kuin "piilotetaan" tuota osaa käyttävältä ohjelmoijalta.

Tämän luvun aiheet liittyvät kaikki tavalla tai toisella tiedon piilottamisen teemaan.

Käyttöliittymät vs. rajapinnat

Rajapinnan käsite kuulostaa samankaltaiselta kuin käyttöliittymän käsite, ja yhteistä niillä onkin.

Ohjelman sisällä on rajapintoja esimerkiksi luokkien välillä. Ne on tarkoitettu ohjelmoijien käytettäviksi.

Käyttöliittymä (user interface eli "käyttäjärajapinta") on koko sovellusohjelman ulospäin näkyvä rajapinta. Sitä käyttää sovelluksen loppukäyttäjä. Koko ohjelmakoodi on tuon rajapinnan toteutus.

Luokkadokumentaatio

Olet jo nähnyt, että ohjelmakirjastot sisältävät käyttökelpoisia komponentteja sovellusten rakentamiseen. Olio-ohjelmoinnin tapauksessa käytetään usein kirjastoja, jotka sisältävät luokkia.

Kirjastoluokan ohjelmakoodiin tutustuminen ei yleensä ole helpoin eikä aina mahdollinenkaan tapa tutustua siihen, miten tiettyä luokkaa käytetään. Käyttäjällehän riittää tietää, mitä käsitettä luokka edustaa ja mitä sillä voi tehdä; hänen on tunnettava luokan rajapinta, mutta toteutuksen hän voi usein jättää huomioimatta.

On yleistä ja kätevää, että käyttäjän tarvitsema rajapinta kuvataan ohjelmakoodista erillisinä, ihmislukijoille tarkoitettuina dokumentteina. Tällaiset dokumentit voi esimerkiksi julkaista web-sivuina.

Scala-luokan dokumentaatio

Tuossa alempana on pieni esimerkki luokkadokumentista: luvusta 2.3 tutun Tyontekija-luokan voi dokumentoida tähän tapaan. Kaikkea dokumentissa näkyvää ei tässä vaiheessa kurssia ole tarpeellista ymmärtää. Suurin osa kuitenkin on hyvin ymmärrettävissä:

  1. Näkyvissä on luokka Tyontekija. Otsikon alla on lyhyt ihmiskielinen kuvaus luokasta.
  2. Kohdassa Instance Constructors kerrotaan, miten luokasta voi luoda ilmentymän: mitä konstruktoriparametreja tarvitaan? Kustakin parametrista on kerrottu sen tyyppi ja lyhyt kuvaus.
  3. Kohdassa Value members on lueteltu aakkosjärjestyksessä Tyontekija-olioiden muuttujat (val, var) ja metodit (def). Kunkin käyttämiseksi tarvittavat piirteet on selitetty lyhyesti.
  4. Oikealla näkyy valikko, josta voi valita tarkasteltavaksi Oliointro-projektista jonkin muun sellaisen osan, jolle on laadittu dokumentaatio. Tässä tapauksessa näin on tehty Asiakas- ja Tilaus- luokille.

Huomasithan koko sisällön? Saat tällaisessa Scaladoc-dokumentissa esimerkiksi metodeista usein huomattavastikin lisätietoa napsauttamalla metodien nimiä, jolloin täydet kuvaukset avautuvat. Tätä tarvitset jatkossa jatkuvasti, eikä asiasta erikseen joka kerta muistutella tässä materiaalissa.

Palautusarvojen tyypit luokkadokumenteissa

Varsinaiseen Scala-koodiin ei ole aina pakko kirjoittaa muuttujien ja palautusarvojen tyyppejä (luku 1.8). Luokkia kuvaaviin dokumentteihin ne on silti aina erikseen kirjoitettu.

Tämä on mainio juttu, koska nuo tyypit ovat osa luokan julkista rajapintaa, ja ne näkemällä luokan käyttäminen onnistuu helpommin.

Huomaa, että myös Unit-palautusarvoisille metodeille (eli "mitään palauttamattomille" metodeille; luku 1.6) on dokumenttiin erikseen kirjattu palautusarvon tyypiksi Unit. Tällainen metodi on esimerkiksi Tyontekija-luokan korotaPalkkaa.

Scaladoc

Monen ohjelmointikielen yhteyteen on luotu apuohjelma, joilla tuonkielisistä ohjelmista voi luoda dokumentaatiota automaattisesti ohjelmakoodin ja sinne kirjoitettujen kommenttien perusteella. Scala-kielen kohdalla tällaisen työkalun nimi on Scaladoc, ja Scala-ohjelmia kuvaavia dokumentteja sanotaan usein Scaladoc-dokumenteiksi tai vain "scaladoceiksi".

Scala API ja sen dokumentaatio

Scaladoc-dokumenteilla on kuvattu myös Scala-kielen valmiit peruskirjastot eli Scala Standard Library API, lyhemmin sanoen vain Scala API (sanoista application programming interface eli "sovellusohjelmointirajapinta" eli sovelluskirjasto; API-lyhennettä käytetään usein suomeksikin). Scala API:iin kuuluvat muun muassa tutut perustietotyypit Int ja Double, matemaattiset funktiot kuten max ja min, puskureita kuvaava luokka Buffer ja paljon muuta.

Scala API:n dokumentaatio on osoitteessa:

Scala API koostuu lukuisista pakkauksista, joiden sisällä on vielä enemmän valmiita luokkia ja yksittäisolioita. Kokonaisuus on laaja, ja siihen sisältyy paljon sellaisia osia, joiden dokumentaation lukeminen ei helposti onnistu ohjelmoinnin vasta-alkajalta. Monia hyvin yleisesti käytettyjäkin työkaluja on virallisessa dokumentaatiossa kuvattu tavalla, joka sopii vain kokeneemmalle lukijalle. Käsittelemme kurssin mittaan eräitä osia Scala API:sta, ja vähitellen ohjelmointi- ja Scala-osaamisesi kehittyy sellaiseksi, että osaat itsenäisesti etsiä lisätietoa Scala API:n dokumentaatiosta.

Scaladocien luominen itse

Tällä kurssilla sinun tarvitsee vain lukea Scaladoc-sivuja, ei luoda niitä itse. Saatat kuitenkin haluta tietää vähän siitä, miten tällaisia sivuja tehdään.

Scala-ohjelmoija voi kirjata perustietoja koodistaan dokumentaatiokommentteihin, jotka alkavat /**-merkinnällä (tavallisen kommentin /*- tai //-merkinnän sijaan). Esimerkiksi Tyontekija-luokan kuukausikulut-metodi voidaan kirjata näin:

/** Palauttaa työntekijän kuukausittaisen hinnan työnantajalleen. Tämä saadaan
  * kuukausipalkan (esim. 4000), työajan (esim. 0.6) ja sivukulukertoimen (esim. 1.3) tulona.
  * @param kulukerroin  sivukulukerroin, työpaikkakohtainen luku, jota käytetään
  *                     työntekijälle aiheutuvien kulujen määrittämisessä */
def kuukausikulut(kulukerroin: Double) = this.kkpalkka * this.tyoaika * kulukerroin

Scaladoc-apuohjelmalla tuotetaan ohjelmakoodin ja tällaisten dokumentaatiokommenttien perusteella yllä olevan kaltaisia HTML-dokumentteja. Työkalusta syvemmin kiinnostuneet voivat lukea lisää Alvin Alexanderin tutoriaalista.

Kurssiprojektien dokumentaatio

Kurssikirjaston O1Library keskeiset luokat kuten Pic, Pos ja View on dokumentoitu doc-kansioon, joka löytyy tuon projektin sisältä. Voit avata kansion sisältämiä dokumentteja sen tutkittavaksi joko Eclipsen sisällä tai erilliseen selaimeen.

Vastaava doc-niminen kansio löytyy myös Oliointro-projektista ja monesta tulevasta kurssin projektista; aivan kaikissa projekteissa ei tosin ole mukana scaladoceja. Samaiset dokumentit ovat tarjolla myös verkossa kurssimateriaalin lukujen alussa olevien "Oheisprojektit"-linkkien kautta.

Opi avaamaan Scaladocit

Ota kokeeksi esiin Oliointro-projektin Scaladocit Eclipseen tai web-selaimeen vähintään yhdellä seuraavista tavoista:

  • Avaa Oliointro-projekti Eclipsen Package Explorerissa ja sieltä doc-kansiosta pääsivu index.html. Koneellasi oleva dokumentaatio avautuu Eclipsen sisäiseen selaimeen.
  • Käyttääksesi erillistä selainta Eclipsen ulkopuolella aloita samoin: avaa Oliointro-projekti Package Explorerissa ja sieltä doc-kansio. Klikkaa hiiren oikealla napilla index.htmlää ja valitse Open With ‣ System Editor. Dokumentaatio avautuu oletusselaimeesi.
  • Käytä tämän sivun alussa olevaa projektilinkkiä. Avautuu sivu, jolta on jatkolinkki verkossa olevaan kopioon dokumentaatiosta.

Parempi rajapinta muuttujien näkyvyyttä säätelemällä

Ongelma: huonosti määriteltyjä rajapintoja

Otetaan uudestaan esille luvussa 2.6 jo käytetty Tilaus-luokka.

class Tilaus(val numero: Int, val tilaaja: Asiakas) {

  var kokonaishinta = 0.0   // kokooja

  def lisaaTuote(kappalehinta: Double, lukumaara: Int) = {
    this.kokonaishinta = this.kokonaishinta + kappalehinta * lukumaara
  }

  // ...
}
Muistamme: kokonaishinta on var-muuttuja, jota on tarkoitus käyttää kokoamaan yhteen kaikkien tuotelisäysten summa.
Muuttujan arvoa kuuluu muuttaa vain, kun lisaaTuote-metodia kutsutaan.

Jos tuo on tavoitteemme luokkaa laatiessa, niin emme ole sitä täysin saavuttaneet. Luokka näet sallii erään sellaisen operaation, jota ei olisi tarkoitus voida tehdä: luokan käyttäjä voi sijoittaa mielivaltaisen arvon kokonaishinnaksi käskyllä jokuTilaus.kokonaishinta = 123456. Tuollainen sijoitus korvaa vanhan arvon eikä huomioi aiempia lisäyksiä uutta arvoa muodostaessaan.

Mahdollisuus sijoittaa kokonaishinta-muuttujaan on nyt siis tarjolla luokan käyttäjälle osana luokan julkista rajapintaa, vaikka moisia sijoituksia oli tarkoitus tehdä vain harkitusti osana luokan sisäistä toteutusta.

Saatat muistaa luvun 2.2 lopusta samantapaisen ongelman, jota ei silloin vielä ratkaistu: tiliolion saldoon saattoi sijoittaa mielivaltaisen arvon, negatiivisenkin, käyttämättä talletus- ja nostometodeita. Tilinkin rajapinta siis tarjoaa toiminnon, jota ei ole tarkoituksenmukaista käyttää.

private-näkyvyysmääre

Käytetään kokonaishinnan tallentamiseen ilmentymämuuttujaa, joka on erikseen määritelty yksityiseksi osaksi luokkaa. Näin estämme tuon muuttujan arvon muuttamisen muualta kuin Tilaus-luokan omasta ohjelmakoodista käsin.

Tässä uusittu koodi, joka ei tosin ole vielä ihan käyttökunnossa:

class Tilaus(val numero: Int, val tilaaja: Asiakas) {

  private var kokonaishinta = 0.0   // kokooja

  def lisaaTuote(kappalehinta: Double, lukumaara: Int) = {
    this.kokonaishinta = this.kokonaishinta + kappalehinta * lukumaara
  }

  // ...
}
Lisätään ilmentymämuuttujan määrittelyyn sana private.

private-sanan vuoksi yritys sijoittaa ilmentymämuuttujaan kokonaishinta tämän samaisen luokan ulkopuolelta ei onnistu:

jokuTilaus.kokonaishinta = -100<console>:9: error: variable kokonaishinta in class Tilaus cannot be accessed in o1.Tilaus
     jokuTilaus.kokonaishinta = -100

Tuolta osin kaikki on hyvin, mutta nyt tämä on ongelma:

println("Hinta yhteensä: " + jokuTilaus.kokonaishinta)<console>:9: error: variable kokonaishinta in class Tilaus cannot be accessed in o1.Tilaus
     println("Hinta yhteensä: " + jokuTilaus.kokonaishinta)

Emme pysty ulkoa päin edes katsomaan, mikä yksityisen muuttujan arvo on. Kuitenkin haluaisimme tilausluokan käyttäjien voivan tutkia tilauksen kokonaishintaa (vaikkeivät voikaan mielivaltaisesti sijoittaa hinnaksi lukuja). No, asia on helposti korjattu:

Yksityinen muuttuja julkisella metodilla

Tämä versio toimii kuten halusimme:

class Tilaus(val numero: Int, val tilaaja: Asiakas) {

  private var lisattyjenHinta = 0.0     // kokooja

  def kokonaishinta = this.lisattyjenHinta

  def lisaaTuote(kappalehinta: Double, lukumaara: Int) = {
    this.lisattyjenHinta = this.lisattyjenHinta + kappalehinta * lukumaara
  }

  // ...
}
Tässä on vaihdettu yksityisen muuttujamme nimeksi lisattyjenHinta, koska...
... määrittelemme metodin nimeltä kokonaishinta (huomaa def). Tämä yksinkertainen metodi vain palauttaa lisattyjenHinta-muuttujan sen hetkisen arvon.

Nyt siis tilausoliolta voi kysyä sen arvoa kokonaishinta-metodilla (esim. jokuTilaus.kokonaishinta), vaikka sijoittaa ei voikaan. Sijoitusyritys jokuTilaus.kokonaishinta = -100 tuottaa virheilmoituksen, koska kokonaishinta ei uudessa versiossamme ole muuttuja vaan parametriton metodi.

Mainittu tiliolioon liittyvä ongelma voidaan ratkaista samalla tavalla private-sanaa käyttämällä: tehdään saldon kirjaavasta muuttujasta yksityinen. (Vapaaehtoinen lisätehtävä: tee tuo parannus tiliin.)

private ja rajapinnat

Kuten näemme, yksityiset muuttujat eivät ole osa luokan julkista rajapintaa vaan osa sen piilotettua toteutusta. Samasta syystä yksityiset muuttujat eivät tule mukaan Scaladoc-dokumentteihin, joiden tehtävä on kuvata luokan käyttötapaa luokan ulkopuolelta katsottuna.

Esimerkiksi Tilaus-luokan dokumentaatiossa ei esiinny nimi lisattyjenHinta. Luokan käyttäjän näkökulmasta on yhdentekevää, minkä nimen luokan toteuttaja on tuolle muuttujalle valinnut tai että muuttuja edes on olemassa. Käyttäjälle oleellista on pääsy julkisiin metodeihin kokonaishinta ja lisaaTuote sekä julkisiin muuttujiin numero ja tilaaja.

Kuten luvussa 2.2 totesimme, ongelmaa ei välttämättä muodostu, jos kukaan luokan käyttäjä ei koskaan tee virheellistä sijoitusta muuttujiin. Kuitenkin on hyvä minimoida virheiden mahdollisuus. private-sana ei estä luokan laatijaa itseään tekemästä virhettä luokkaa toteuttaessaan, mutta olettaen hänen hoitavan hommansa hyvin, ei kukaan (hän itsekään!) voi tehdä virhesijoitusta luokkaa käyttäessään.

Luokka on yksinkertaisempi ja käytettävämpi, jos luokkaa käyttävälle ohjelmoijalle ei tarjota sellaisia mahdollisuuksia, joista ei ole hyötyä. Kun luokka on käytettävämpi, ovat ohjelmoijat tuotteliaampia ja ohjelmat toimivampia. Luokassa kuten televisiossakaan ei toivottavasti ole nappulaa, joka rikkoo laitteen, jos käyttäjä sitä menee epähuomiossa painamaan. Vaikka käyttäjä ei nappulaa painaisikaan, joutuisi hän ihmettelemään, miksi se on siinä ja varomaan sitä.

private ja paikalliset muuttujat

Tässä on yksi aiemmista esimerkkifunkioistamme:

def verot(tulot: Double, tuloraja: Double, perusprosentti: Double, lisaprosentti: Double) = {
  val perusosa = min(tuloraja, tulot)
  val lisaosa = max(tulot - tuloraja, 0)
  perusosa * perusprosentti + lisaosa * lisaprosentti
}
Koodiin on määritelty (parametrimuuttujien lisäksi) kaksi paikallista muuttujaa. Voisiko nämä muuttujat määritellä yksityisiksi? Pitäisikö ne?

Valitse alta se vaihtoehto, joka parhaiten kuvaa mitä perusosa- ja lisaosa- muuttujien kanssa olisi hyvä tehdä. Päättele ja kokeile.

Yksityisistä metodeista

On mahdollista ja usein hyödyllistäkin määritellä myös metodeita, jotka ovat yksityisiä ja siis tarkoitettu vain luokan tai yksittäisolion sisäiseen käyttöön. Tästä näet esimerkkejä monessa myöhemmässä luvussa (mm. 3.6).

FlappyBug-tehtävä (osa 10/17: private käyttöön)

Kun käytämme var-muuttujaa kuvaamaan olion muuttuvaa tilaa, ei ole lainkaan harvinaista, että haluamme tilaus- ja tiliesimerkin tapaan rajata sitä, miten tuon muuttujan arvoa voi vaihtaa. Itse asiassa käyttökohteita private-muuttujille voi löytää lisääkin jo kohtaamiemme ohjelmien joukosta, esimerkiksi FlappyBug-pelistä.

Obstacle-luokan muokkaus

Jatketaan viime kierroksella syntyneen FlappyBug-version pohjalta. (Jos et tehnyt noita tehtäviä viime kierroksella, käy aiemmat vaiheet nyt läpi. Voit käyttää niiden esimerkkiratkaisuja, jotka löytyvät linkeistä tehtävien kohdalta määräajan jälkeen.)

Tässä toistainen Obstacle-luokka:

class Obstacle(val radius: Int, var pos: Pos) {

  def approach() = {
    this.pos = this.pos.addX(-ObstacleSpeed)
  }

  override def toString = "center at " + this.pos + ", radius " + this.radius
}
Tavoitteenamme on, että approach-metodi hallinnoi esteen liikettä yksinoikeudella. Muualla tähän muuttujaan ei sijoiteta.
Muuttuja pos on var-muuttuja ja julkinen. Kuitenkaan suunnittelemamme pelin kannalta ei ole tarkoituksenmukaista, että luokan käyttäjä "teleporttaisi" esteen jonnekin sijoittamalla pos-muuttujalle jonkin mielivaltaisen arvon. Joten älkäämme edes tarjotko käyttäjälle tätä mahdollisuutta.

Tässä uusittu versio:

class Obstacle(val radius: Int, initialPos: Pos) {

  private var currentPos = initialPos

  def pos = this.currentPos

  def approach() = {
    this.currentPos = this.currentPos.addX(-ObstacleSpeed)
  }

  override def toString = "center at " + this.pos + ", radius " + this.radius
}
Konstruktoriparametri. Huom. ei val-sanaa edessä. Jos olisi, tästä tulisi (julkinen) ilmentymämuuttuja.
Yksityinen ilmentymämuuttuja.
Julkinen metodi, jolla luokan käyttäjä saa esteen sijainnin selville.
Nyt ainoa tapa liikuttaa estettä on kutsua sen approach-metodia, kuten halusimme.

Sama toisin kirjoitettuna

Yllä määriteltiin erikseen konstruktoriparametri initialPos ja yksityinen ilmentymämuuttuja currentPos, jolloin korostuu, että juuri ilmentymämuuttuja on se, jonka näkyvyyttä säädämme private-määreellä.

Tämä hieman lyhyempikin versio toimii:

class Obstacle(val radius: Int, private var currentPos: Pos) {

  def pos = this.currentPos

  def approach() = {
    this.currentPos = this.currentPos.addX(-ObstacleSpeed)
  }

  override def toString = "center at " + this.pos + ", radius " + this.radius
}
Määritellään konstruktoriparametrin yhteydessä sitä vastaava ilmentymämuuttuja ja tehdään saman tien tuosta ilmentymämuuttujasta yksityinen.

Tehtävänanto

  1. Muokkaa Obstacle-luokkaa omassa projektikopiossasi yllä kuvatulla tavalla.
  2. Tee sama muutos myös Bug-luokkaan: pidä ötökän sijainti tallessa yksityisessä muuttujassa ja tarjoa julkinen metodi pos, joka palauttaa sen arvon.
    • Nyt siis ötökkää liikutetaan vain fall- ja flap-metodeilla (jotka samalla huolehtivat ötökän pysymisestä pelikentän sisällä!).
    • Luokkaasi ei saa jäädä julkista muuttujaa nimeltä pos.
    • Varmista myös, ettei luokassasi ole muitakaan sellaisia julkisia osia, joita ei erikseen ole pyydetty. Sillä ei pidä olla esimerkiksi initialPos-nimistä julkista muuttujaa.
  3. Määrittelit luvun 3.1 tehtävässä muuttujan yVelocity. Tee myös siitä yksityinen, jotta luokan käyttäjä ei voi mielivaltaisesti sen arvoa muutella.
    • Koska luokan käyttäjän ei itse asiassa tarvitse tehdä ötökän nopeudella mitään, riittää, että lisäät private-sanan muuttujan määrittelyyn. Sinun ei tarvitse määritellä julkista metodia tämän muuttujan arvon tutkimiseen.

Palauttaminen

A+ esittää tässä kohdassa tehtävän palautuslomakkeen.

Löydätkö lisää?

Löydätkö kurssilla jo esiintyneistä ohjelmista muita ilmentymämuuttujia, jotka voisi olla perusteltua määritellä yksityisiksi?

Katso esimerkiksi Laskuri-luokkaa.

Kysymyksiä pohdittaviksi

Miksi esiin nostetuissa esimerkeissä yksityisiksi määriteltiin juuri var-muuttujia? Eroavatko var- ja val-muuttujat tässä suhteessa toisistaan?

Miksei vaikkapa Pos-luokassa (luku 2.5) synny vastaavaa tarvetta yksityiselle muuttujalle?

Voiko olla perusteltua tehdä val-muuttujasta yksityinen?

Palaamme näihin teemoihin luvun 4.1 lopussa.

Yhteenvetoa

  • Luokista ja yksittäisolioista voi laatia dokumentaatiota, joka kuvaa niiden käytön kannalta oleelliset piirteet.
    • Tällaisilla Scaladoc-dokumenteilla on kuvattu esimerkiksi Scala-kielen peruskirjastot ja kurssin o1-kirjasto.
  • Luokkien osia voi määritellä yksityiseksi private-näkyvyysmääreellä, jolloin niitä voi käsitellä vain luokan itsensä ohjelmakoodista.
  • Lukuun liittyviä termejä sanastosivulla: julkinen, yksityinen, rajapinta, toteutus, tiedon piilottaminen, abstraktio; dokumentaatio, Scaladoc, API eli sovelluskirjasto.

Palaute

Huomaathan, että tämä on henkilökohtainen osio! Vaikka olisit tehnyt lukuun liittyvät tehtävät parin kanssa, täytä palautelomake itse.

Tekijät

Tämän oppimateriaalin kehitystyössä on käytetty apuna tuhansilta opiskelijoilta kerättyä palautetta. Kiitos!

Kierrokset 1–13 ja niihin liittyvät tehtävät ja viikkokoosteet on laatinut Juha Sorva.

Kierrokset 14–20 on laatinut Otto Seppälä. Ne eivät ole julki syksyllä, mutta julkaistaan ennen kuin määräajat lähestyvät.

Liitesivut (sanasto, Scala-kooste, usein kysytyt kysymykset jne.) on kirjoittanut Juha Sorva sikäli kuin sivulla ei ole toisin mainittu.

Tehtävien automaattisen arvioinnin ovat toteuttaneet: (aakkosjärjestyksessä) Riku Autio, Nikolas Drosdek, Joonatan Honkamaa, Jaakko Kantojärvi, Niklas Kröger, Teemu Lehtinen, Strasdosky Otewa, Timi Seppälä, Teemu Sirkiä ja Aleksi Vartiainen.

Lukujen alkuja koristavat kuvat ja muut vastaavat kuvituskuvat on piirtänyt Christina Lassheikki.

Yksityiskohtaiset animaatiot Scala-ohjelmien suorituksen vaiheista ovat suunnitelleet Juha Sorva ja Teemu Sirkiä. Niiden teknisen toteutuksen ovat tehneet Teemu Sirkiä ja Riku Autio käyttäen Teemun toteuttamia Jsvee- ja Kelmu-työkaluja.

Muut diagrammit ja materiaaliin upotetut vuorovaikutteiset esitykset on laatinut Juha Sorva.

O1Library-ohjelmakirjaston ovat kehittäneet Aleksi Lukkarinen ja Juha Sorva. Useat sen keskeisistä osista tukeutuvat Aleksin SMCL-kirjastoon.

Opetustapa, jossa käytämme O1Libraryn työkaluja (kuten Pic) yksinkertaiseen graafiseen ohjelmointiin on saanut vaikutteita tekijöiden Flatt, Felleisen, Findler ja Krishnamurthi oppikirjasta How to Design Programs sekä Stephen Blochin oppikirjasta Picturing Programs.

Oppimisalusta A+ on luotu Aallon LeTech-tutkimusryhmässä pitkälti opiskelijavoimin. Pääkehittäjänä toimii tällä hetkellä Jaakko Kantojärvi, jonka lisäksi järjestelmää kehittävät useat tietotekniikan ja informaatioverkostojen opiskelijat.

Kurssin tämänhetkinen henkilökunta on kerrottu luvussa 1.1.

Lisäkiitokset tähän lukuun

Luvun alun videon tekivät Kimmo Kiiski ja Teemu Havulinna né Koskinen. Käsikirjoittamiseen osallistui myös muuta Aallon Tietotekniikan laitoksen opetushenkilökuntaa.

a drop of ink
Palautusta lähetetään...