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

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

Luku 2.1: Olio-ohjelmointi

Tästä sivusta:

Pääkysymyksiä: Miten kuvaan ohjelman aihepiirin tietokoneelle? Miten jäsennän isomman ohjelmakokonaisuuden osiksi — olioiksi — jotka toimivat yhteen? Miten komennan oliota Scalalla?

Mitä käsitellään? Ohjelmointi käsitteiden mallintamisena. Olio-ohjelmointi: oliot ja metodit, olioiden välinen viestintä. Yksittäisoliot Scalassa: metodin kutsuminen, viittaukset olioihin.

Mitä tehdään? Ensin luetaan. Lopussa myös kokeillaan olioiden käyttöä konkreettisesti koodissa.

Suuntaa antava työläysarvio:? Vajaat pari tuntia, jos — kun — käyt kaikki esimerkit ajatuksella läpi. Luku voi olla haastava: olio-ohjelmoinnin peruskäsitteet saattavat ensi alkuun tuntua abstrakteilta tai muuten vierailta.

Pistearvo: A25.

Oheismoduulit: Oliointro (uusi).

../_images/person06.png

Johdanto

Olet tähän mennessä oppinut erilaisia ehkä hieman sekalaisiltakin tuntuvia ohjelmointitekniikoita: lausekkeet, muuttujat, viittaukset, funktiot, tietotyypit ja niin pois päin.

Unohda ne nyt hetkeksi.

Tässä luvussa vaihdamme näkökulmaa ja tarkastelemme laajemman ohjelmakokonaisuuden laatimista sekä sitä ohjelmointitapaa, jota tällä kurssilla käytämme ohjelmien jäsentämiseen: olio-ohjelmointia.

Voidaan ajatella, että kaikki aiemmat luvut ovat olleet eräänlainen alkusoitto sille työlle, joka alkaa tästä luvusta ja jatkuu läpi kurssin. Jo tämän luvun lopussa alkaa paljastua, miten aiemmin opitut asiat liittyvät tämän luvun aiheeseen. Itse asiassa nuo aiemmat aiheet oli valittu alkusoiton säveliksi juuri siksi, että niistä on hyötyä olio-ohjelmoinnin käytännön oppimisessa.

Kurssi alkaa tästä.

Käsitteiden mallintaminen

Kommunikaatio-ongelma

../_images/communication_prob.png

Ongelma.

Ohjelmat käsittelevät monimuotoista dataa. Pelkät kokonaislukujen laskutoimitukset, merkkijonojen yhteen liittämiset tai ympyrän piirtämiset eivät riitä. Haluamme, että ohjelmamme "tallentaa tiedoston", "ilmoittaa opiskelijan kurssille", "lisää hotellikokemuksen päiväkirjaan", "reagoi nappulan painallukseen", "nostaa rahaa tililtä" tai "valitsee vihollisen seuraavan siirron".

Kohtaamme ongelman. Ihmisajattelu ja -kieli on käsitteellistä, mutta tietokone ei ymmärrä reaalimaailman käsitteitä. Mikä on "kurssi", "opiskelija", "hotelli" tai "pankkitili"?

Ohjelmointikieli ei voi sisältää yksiselitteisiä määrittelyjä kaikille maailman käsitteille. Kuitenkin kone tarvitsisi yksiselitteiset määritelmät voidakseen suorittaa aihepiiriin liittyviä ohjelmia.


../_images/communication_sol.png

Määritellään käsitteitä ohjelmakoodissa.

Ongelman ratkaisu

Ollaan ihmislähtöisiä: laaditaan ohjelmia, jotka ovat koneen käsiteltävissä mutta jotka heijastavat sitä, miten olemme ihmisinä jäsentäneet ohjelman "maailman". Määritellään tarvitsemamme käsitteet ja niitä vastaavat termit tietokoneelle!

Tarkoituksenamme on siis laatia malli siitä, mitä erilaiset ohjelmamme aihealueeseen (domain) liittyvät käsitteet ovat eli mitä tietoa ja toimintoja niihin liittyy. Koska ohjelmointikieleen itseensä ei voi kirjata kaikkia käsitteitä, on kielen tarjottava mahdollisuus käsitteiden kuvaamiseen.

Olio-ohjelmointi, eräs ohjelmointiparadigma

Vuosien saatossa on syntynyt erilaisia tapoja ohjelmoida, niin sanottuja ohjelmointiparadigmoja (programming paradigm). Ohjelmointiparadigmat eroavat toisistaan muun muassa siltä osin, millaisia työkaluja niissä käytetään asioiden mallintamiseen.

paradigma: perusnäkemys, malli, esikuva tai viitekehys, jota sen puitteisiin sopeutuva toiminta ei aseta kyseenalaiseksi.

—eräs määritelmä sanalle "paradigma" WSOY:n Ison tietosanakirjan pohjalta

Tällä kurssilla keskipisteessä on eräs paradigma: olio-ohjelmointi (object-oriented programming, OOP). Olio-ohjelmointi on suosittu ja mielenkiintoinen ohjelmointiparadigma. Scala on eräs olio-ohjelmointiin hyvin sopiva kieli.

Paradigmat O1-kurssilla

Jotkin ohjelmointiparadigmat ovat toisilleen vaihtoehtoisia, mutta kaikki eivät suinkaan ole toisiaan pois sulkevia; on mahdollista tukeutua useaan paradigmaan yhtä aikaa. Esimerkiksi Scala-kieli on tarkoituksellisesti suunniteltu niin, että sillä voi ohjelmoida erilaisilla tavoilla ja helppoa myös yhdistellä eri tapoja. Tällä kurssilla yhdistämme olio-ohjelmointiin enimmäkseen imperatiivista ohjelmointia (imperative programming) mutta myös funktionaalista ohjelmointia (functional programming). Näistä toisista paradigmoista lisää myöhemmin luvussa 10.2.

Kurssilla syleilemme olioita melko estottomasti. Olio-ohjelmoinnilla on hienoja piirteitä. Kuitenkin on hyvä jo alustavasti tiedostaa, että se ei ole kaikkeen aina parhaiten tepsivä poppakonsti. Olio-ohjelmoinnin vaihtoehtoja kohtaat muilla ohjelmointikursseilla (ja lyhyesti luvussa 10.2).

Olio-ohjelmoinnissa korostuu ajatus käsitteiden mallintamisesta. Yksittäistä kurssia, opiskelijaa, pankkitiliä, käyttöliittymäikkunaa tai -nappulaa vastaa olio-ohjelmassa yksi "olio".

Oliot

Mikä on yhteistä kalalle, trumpetille ja piipulle?
Entäpä mitä on hyvyys ja kampela?
Asioitapa tietenkin ovat ne. — —
Maailma on asioita pullollaan!

—Ultra Bra

object: something mental or physical toward which
thought, feeling, or action is directed

—Merriam-Webster Online

../_images/object_car-fi.png

Olio metodeineen piirroksen muodossa kuvattuna.

Olio ("asia", "objekti"; object) on jonkin asian kuvaamiseen käytetty abstraktio olio-ohjelmassa. Yleensä kuhunkin olioon liittyy toimintoja eli metodeita (method), joilla oliota voi hyödyntää. Esimerkiksi autoa voitaisiin kuvata oliona, jolla on metodeja kuten "aja", "lisää matkustaja", "tankkaa", "kerro bensan määrä" ja niin edelleen.

Olioon liittyy usein myös ominaisuuksia, jotka kuvaavat sen pysyviä tai muuttuvia piirteitä. Esimerkiksi auto-olion tietoja voisivat olla sen merkki, bensatankin sisältämän bensan määrä, sijainti ja matkustajat.

Ohjelmoija valitsee, mitä ominaisuuksia ja metodeita olioihin liittyy. Valintaperusteena on se, mitkä asiat on tarpeen mallintaa käsillä olevan ongelman ratkaisemiseksi. Esimerkiksi auton valmistaja voi olla merkityksellinen tieto jossakin ohjelmassa mutta merkityksetön toisissa. Kun tietokone suorittaa ohjelman, se pitää olioita tallessa muistissaan ohjelmoijan määrittelemällä tavalla.

Jotakuinkin mitä tahansa voi kuvata oliona. Tässä muutamia esimerkkejä graafisessa muodossa:

../_images/object_many-fi.png

Huomaa tästä kuvastakin, että olioilla on sekä tietoja, jotka niihin liittyvät (esim. opiskelijaolion opiskelijanumero, nappulaolion teksti), että toimintoja, joita niihin voi kohdistaa (esim. opiskelijan lisääminen kurssille, tiedoston poistaminen). Huomaa myös, että oliot voivat muistuttaa toisiaan — olla keskenään samaa tyyppiä — kuten kaksi eläinoliota yllä.

Olioista koostuvat mallit

Olioita yhdistelemällä voimme luoda ohjelman aihepiiriä kuvaavan mallin. Tässä yksi pieni esimerkki piirroksen muodossa:

../_images/object_mycoursesish-fi.png

Olioita, jotka liittyvät kuvitteelliseen (yksinkertaistettuun) kurssi-ilmoittautumisjärjestelmään. Huomaa, miten oliot viittaavat toisiinsa ja muodostavat kokonaisuuden.

Kullakin oliolla on oma vastuualueensa ohjelman toiminnassa. Esimerkiksi kurssiolion vastuulla voi olla kirjanpito siitä, keitä kurssille on ilmoittautunut, sekä uusista ilmoittautumisista huolehtiminen enimmäisosallistujamäärän puitteissa. Eri olioiden toimintoja yhdistelemällä saadaan aikaan koko ohjelman toiminta.

Olioilla voi myös mallintaa ohjelman käyttöliittymää. Ajatellaan vaikkapa tämän näköistä käyttöliittymäikkunaa:

../_images/feedback_form-fi.png

Tätä ikkunaa voi kuvata Scala-ohjelmassa olioista koostuvalla mallilla, joka näyttää suunnilleen tältä:

../_images/object_feedback-fi.png

Antropomorfinen näkökulma olioihin

../_images/sir_yes_sir.png

Olio-ohjelmoinnin ymmärtämisessä voi auttaa ajatusleikki, jossa oliot mielletään ihmismäisiksi toimijoiksi ja kukin olio on, jos ei "älykäs", niin ainakin "kyvykäs" omalla rajallisella tavallaan.

Kukin olio "tietää", millainen se itse on, eli tuntee omat ominaisuutensa. Esimerkiksi auto-olio tietää tankissa olevan bensan määrän ja kurssiolio kurssille ilmoittautuneet opiskelijat.

Olio osaa vastaanottaa viestejä ("käskyjä", "pyyntöjä") sen mukaisesti, millaiset metodit sille on määritelty. Esimerkiksi kurssioliota voi komentaa kirjaamaan opiskelijan ilmoittautuneeksi, auto-oliota tankkaamaan itsensä tai tiedosto-oliota poistamaan edustamansa datan kiintolevyltä. Olio ei osaa vastaanottaa sellaista viestiä, jota vastaavaa metodia sillä ei ole.

Kullakin oliolla on käyttäytymismalli, joka määrää, miten olio reagoi vastaanottamiinsa viesteihin. Käyttäytymismallin määrittelee ohjelmoija hyödyntäen ohjelmointikielen tarjoamia mahdollisuuksia. Olion voi määritellä esimerkiksi suorittamaan laskutoimituksia, kirjaamaan tietoja muistiin, lähettämään viestejä muille olioille, luomaan uusia olioita jne.

Olio on ehdottoman kuuliainen ja noudattaa ohjelmoijan sille antamia ohjeita pilkulleen. Olio-ohjelmointi(kin) vaatii siis huolellisuutta, täsmällisyyttä ja yksiselitteistä kieltä.

Olioiden välinen viestintä

Yksi olio ei paljoon pysty, mutta hallitussa yhteistyössä oliot voivat saada aikaan paljonkin. Tarkastellaan kahta esimerkkiä.

GoodStuff-esimerkki

Miten luvun 1.2 GoodStuff-sovellus kokonaisuutena toimii, kun sitä käytetään GUI:sta käsin? Esimerkiksi: Mitä tapahtuu, kun käyttäjä painaa Add experience-nappulaa? Silloinhan pitäisi saada lisättyä tietynlainen kokemusmerkintä ja tarvittaessa päivitettyä suosikkiustietoa.

GoodStuff-ohjelman oliot hyödyntävät toistensa metodeita eli "komentavat toisiaan". Ohjelman suoritus muodostuu olioiden välisestä viestinnästä ja viesteihin reagoinnista. Seuraava vuorovaikutteinen esitys antaa yleiskuvan ohjelman toiminnasta eräässä esimerkkitapauksessa. Vaikka esitys on abstrakti ja graafinen, se vastaa hyvin pitkälti GoodStuff-ohjelman todellista teknistä toteutusta.

Olioiden välinen viestintä kuvattiin yllä puhekuplina, mutta puhekuplien viestit voi ilmaista myös Scala-kielen käskyinä. Vaikka nämä käskyt eivät vielä tuttuja olekaan, niin voit jo halutessasi tutkia seuraavia Scala-koodinpätkiä ja arvailla, mihin äskeisen esimerkin vaiheisiin ne liittyvät.

new Experience(name, description, price, rating)
this.experiences += newExperience
newExperience.chooseBetter(this.fave)
if (this.isBetterThan(another)) this else another
this.favorite = newExperience
category.addExperience(newExperience)

Kaikki mainitut käskyt tulevat tutummiksi kurssin edetessä.

Kurssi-ilmoittautumisesimerkki

Seuraava esimerkki on pääpiirteissään samanlainen kuin edellinenkin. Siihenkin kannattaa silti tutustua ymmärryksen vahvistamiseksi. Voit ohittaa esimerkin, jos on armoton kiire tai jos kaikki tuntuu täysin selvältä. Laiskuuden vuoksi ohittaminen on sen sijaan kielletty.

Ajatellaan kuvitteellista sovellusohjelmaa, jonka avulla opiskelija voi ilmoittautua kursseille painamalla kyseiseen kurssiin liittyvää nappia ohjelman käyttöliittymässä. Tällöin ohjelman tulee selvittää, onnistuuko ilmoittautuminen. Ilmoittautuminen onnistuu, jos opetussaliin mahtuu ja jos sama opiskelija ei ole jo ennestään ilmoittautunut. Ilmoittautumisen onnistuessa täytyy kirjata sekä opiskelija kurssin opiskelijaluetteloon että kyseinen kurssi opiskelijan omiin kursseihin.

Luonnos yhdestä olioita käyttävästä ratkaisusta on kuvattu alla:

Pohdintoja olio-ohjelmista

Olio-ohjelman tila

Olio-ohjelman kaikkien olioiden tilat muodostavat yhdessä koko ohjelman tilan. GoodStuff-sovelluksessa ohjelman tilaan sisältyvät kategoriaolion tila (nimi, suosikki ja tieto siitä, mitkä kokemukset on kirjattu) sekä kunkin kokemusolion tiedot (kuvaukset, arvosanat ja hinnat).

Olioiden toimiessa saamiensa käskyjen mukaisesti niiden tilat voivat muuttua ja samalla koko ohjelman tila. Esimerkkejä: lisätään uusi kokemus päiväkirjaan, lisätään opiskelija ilmoittautuneeksi jollekin kurssille, vaihdetaan käyttäjän henkilötietoja jne.

Olio-ohjelman suorittaminen

Olio-ohjelman olioiden muodostama käsitteellinen malli jäsentää ohjelman ihmisen kannalta järkeväksi kokonaisuudeksi. Jokaisella oliolla on tässä mallissa oma vastuualueensa, jota se hoitaa ohjelmaa ajettaessa. Pohjimmiltaan ohjelma-ajo on silti vain sarja peräkkäisiä komentoja, joita tietokone suorittaa. Ohjelmoija määrittelee käskyt olioiden yhteyteen metodeiksi. Osa metodeista saa oliot komentamaan toisiaan: olio ikään kuin siirtää toimintavuoron komentamalleen oliolle ja jää odottamaan; vain yksi olio kerrallaan on aktiivinen.

Olioiden metodit toteuttavat ohjelman osa-algoritmeja, ja niitä yhdistelemällä saadaan aikaan kokonainen algoritmi, joka suorittaa ohjelmalta vaaditut tehtävät.

Olioiden välisistä viesteistä tarkemmin

Viimeistään tämän kappaleen aikana alkaa varmaan tämäkin luku kuulostaa kovin tutulta.

Metodin kutsuminen

Oliolle lähetetyt viestit aktivoivat olion metodeita. Tällaisen viestin lähettämistä sanotaan metodin kutsumiseksi (method call, method invocation). Tässä kutsutaan auto-olion "aja"-nimistä metodia:

../_images/object_method_car_drive-fi.png

Jotkut metodikutsut yksinkertaisesti pyytävät oliota kertomaan tietyn tilatiedon, kuten bensan määrän tankissa. Toiset tekevät jotakin monimutkaisempaa.

Viestin lisätiedot eli parametrit

Metodiparametreilla voi välittää oliolle lisätietoja siitä, mitä olion tulisi tehdä. Tässä tankattavan bensan määrä välitetään parametriksi (mikä on korostettu keltaisella):

../_images/object_method_car_refuel_10-fi.png

Parametreiksi voi antaa erilaisia arvoja: lukuja, viittauksia toisiin olioihin ja niin edelleen.

Parametreja voi olla yksi tai useampia. Ja voi niitä olla nollakin, kun viesti itsessään kertoo kaiken oleellisen kuten tässä:

../_images/object_method_car_getfuel-fi.png

Vastausviestit eli palautusarvot

Monesti olio vastaa metodikutsuun jollain tapaa eli lähettää kutsujalle jotakin vastausviestinä. Sanotaan, että metodi palauttaa arvon. Metodin palautusarvo voi olla esimerkiksi tieto toiminnon onnistumisesta tai epäonnistumisesta:

../_images/object_method_car_refuel_10_ok-fi.png

Palautusarvo voi myös olla tilannetieto olion tilasta:

../_images/object_method_car_getfuel_20-fi.png

Pikkutehtävä olioista ja metodeista

Arvioi seuraavia väitteitä sen perusteella, mitä tässä luvussa on olio-ohjelmoinnista kerrottu. Kaikkiin kohtiin ei ole yllä annettu suorasanaista vastausta, mutta kaikkien kohtien vastaus on pääteltävissä luvun sisällöstä.

Mieti huolellisesti. Esitä paras arviosi, ja katso palaute. Ei ole välttämätöntä saada "ekalla oikein". Tämä(kin) tehtävä palautteineen on osa oppimisprosessia, ei pelkkä testi siitä, mitä olet aiemmin oppinut.

Valitse paikkansa pitävät väitteet.
Valitse paikkansa pitävät väitteet.

Metodit ovat olioihin liitettyjä funktioita

Tässä luvussa on puhuttu kutsumisesta, parametreista ja palautusarvoista. Nuo metodeihin liittyvät termit ovat ihan ne samat, jotka jo kohtasit viime kierroksella funktioista puhuttaessa. Se ei toki ole sattumaa: metodit ovat funktioita, jotka on määritelty olioiden yhteyteen. Näillä olioiden funktioilla on pääsy olion tietoihin, ja ne hoitavat olion vastuualueelle kuuluvia asioita: ne määrittelevät, mitä olio osaa tehdä.

Olioiden välinen viestintä toteutuu niin, että tietyn olion funktion (metodin) ohjelmakoodista kutsutaan toiseen olioon liitettyä funktiota.

Vaikka voitaisiin tietysti puhua "olioiden funktioista", on "metodi"-termi hyvin vakiintunut. Tälläkin kurssilla olioiden funktioita kutsutaan yleensä metodeiksi.

Voimme sijoittaa olio-ohjelmoinnin peruskäsitteet kaavioomme:

Oliot ja Scala

Scala-kieli tarjoaa työkalut yksittäisolioiden (singleton object) määrittelemiseen: voimme kirjoittaa ohjelmakoodia, joka määrittelee, mitä piirteitä yhdellä tietyllä oliolla on. Kun olio metodeineen on määritelty, sitä voi komentaa Scala-käskyillä.

Seuraavaksi opettelet olio-ohjelmoinnin perusteita koekäyttämällä valmiiksi määriteltyjä yksittäisolioita ja niiden metodeita ennen kuin pääset määrittelemään uusia olioita ja metodeita itse seuraavassa luvussa. Draaman kaari on siis samanlainen kuin luvuissa 1.61.8, joissa ensin koekäytit valmiiksi määriteltyjä funktioita ennen kuin siirryit itse toteuttamaan omia.

Jotta saamme oliota komennettua, meidän pitää pystyä ilmoittamaan tietokoneelle se, mille oliolle haluamme viestin lähettää, sekä se, mitä tuon olion metodeista haluamme kutsua. Seuraavassa esimerkissä tehdään näin ja koekäytetään erästä oliota.

Papukaijajohdanto

Esimerkkinämme toimikoon "virtuaalipapukaija". Papukaijaoliolla on tietty repertuaari lauseita (merkkijonoja), jotka se on oppinut sanomaan ja joita se laukoo "kuullessaan" tuttuja sanoja. Papukaijaa komennetaan puhumaan kutsumalla sen vastaa-nimistä metodia, jolle annetaan papukaijan kuulema lause parametriksi:

../_images/object_method_parrot_respond-fi.png

Papukaijan vastaa-metodin kutsuminen. Metodin nimi on korostettu punaisella, parametri keltaisella ja palautusarvo vihreällä.

Virtuaalipapukaijamme on määritelty Oliointro-moduulissa. Ennen kuin lähdemme kutsumaan sen metodeita, nouda Oliointro kurssiprojektiisi IntelliJ’ssä ja käynnistä REPL tuohon moduuliin.

Metodikutsu Scalalla

Kutsutaan papukaijan vastaa-metodia ja annetaan parametriksi eräs merkkijono:

papukaija.vastaa("Maistuisiko keksi?")res0: String = Polly tahtoo keksin!
Metodikutsu aloitetaan ilmoittamalla viestin vastaanottaja eli kohdeolio. Tämä käy kirjoittamalla lauseke, jonka arvo on viittaus johonkin olioon. Kurssin tarjoamassa valmiissa pakkauksessa on määritelty, että nimi papukaija viittaa yksittäiseen papukaijaolioon.
Kohdeolion perään tulee piste.
Loput metodikutsusta on tuttua: metodin nimi, sitten kaarisulkeisiin parametrilauseke tai lausekkeet aivan kuin jo kohtaamillemme funktioille. (Muista: metodit ovat olioihin liitettyjä funktioita.) Tässä parametriksi vastaa-metodille annetaan jokin merkkijono, jonka papukaija "kuulee" ja johon se vastaa.
Metodin palautusarvona saadaan papukaijaolion omalla sisäisellä logiikallaan valitsema merkkijono.

Tässä vielä neljä esimerkkiä papukaijaolion vastaa-metodin kutsumisesta. Kukin käskyistä antaa parametriksi eri merkkijonon:

papukaija.vastaa("Maistuisiko keksi?")res1: String = Polly tahtoo keksin!
papukaija.vastaa("Onko nimesi siis Polly?")res2: String = Polly tahtoo keksin!
papukaija.vastaa("Mitä kuuluu?")res3: String = Mitä!
papukaija.vastaa("Terve vaan sitten.")res4: String = Terve!

Tärkeintä tässä esimerkissämme on, että näet, miten oliota — joka sattuu nyt olemaan eräänlainen papukaijaolio — komennetaan. Se, millä perusteella tämä papukaijaolio on määritelty vastauksensa valitsemaan, ei sinänsä ole tärkeää, mutta jos tiedät siitä tämän verran, sujuu esimerkin seuraaminen paremmin:

Kun papukaija kuulee sanan, joka muistuttaa sen tuntemassa lauseessa esiintyvää sanaa, se vastaa toistamalla tuon lauseen. Tämän papukaijan repertuaariin kuuluu lause "Polly tahtoo keksin", jossa esiintyvät sekä "keksi" että "Polly". Papukaija tunnistaa sanan, jos sanan Levenštein-etäisyys (luku 1.6) tutun lauseen sanasta on korkeintaan yksi; esimerkiksi sanojen "keksi" ja "keksin" etäisyyshän on juuri yksi.
Papukaija on määritelty käyttäytymään niin, että kun sen kuulema lausahdus ei osu sen repertuaariin, se vain toistaa ensimmäisen kuulemansa sanan.

Voit myös itse vapaasti kokeilla papukaijaolion käyttöä. Valitse REPLiä käynnistäessäsi Oliointro-moduuli.

Pikkutehtävä: kaija-analyysi

Papukaijan repertuaariin kuuluu kaksi lausetta, joista yhdeksi olemme todenneet "Polly tahtoo keksin". Kokeile metodikutsu(j)a käyttäen, mikä on toinen papukaijan osaama lause. Vinkki: mainitse sille "rommi".

Toinen virtuaalipapukaijan osaamista lauseista on:

Olion tila

Vielä äskeisen esimerkin perusteella voisi ajatella, että olio on vain joukko funktioita, joihin pääsee käsiksi tietyn nimen kautta. Olio ei kuitenkaan ole vain sitä.

Luvun alun esimerkeistä kävi jo ilmi, että oliolla on omat tiedot, jotka muodostavat sen tilan. Olio käyttää tilatietojaan apuna: tilalla voi olla merkitystä siihen, mitä tapahtuu olion reagoidessa metodiensa kutsumiseen. Jotkin tiedot voivat olla muuttumattomia (esim. auto-olion merkki), ja joidenkin olioiden tila ei koskaan muutu miltään osin. Kuitenkin monilla olioilla on metodeita, jotka vaikuttavat olion tilaan (esim. auto-olion sijaintiin ja bensamäärään; pankkitiliolion saldoon).

Papukaijallammekin on metodi, joka vaikuttaa sen tilaan kasvattamalla papukaijan repertuaaria:

papukaija.vastaa("Hei mä tykkään susta tosi paljon")res5: String = Hei!
papukaija.opiLause("Jaa, minä tykkään, että sinä olet yksi styränki")papukaija.vastaa("Hei mä tykkään susta tosi paljon")res6: String = Jaa, minä tykkään, että sinä olet yksi styränki!
Aluksi papukaija ei osaa tämän lauseen sanoja vaan toistaa vain lauseen ensimmäisen sanan.
Virtuaalipapukaijamme on hanakka oppimaan: riittää, kun kutsumme sen opiLause-metodia ja annamme parametriarvoksi uuden virkkeen. opiLause ei palauta kuin Unitin, eikä mitään palautusarvoa siis tulostu REPLiin.
Uusi vastaa-kutsu todentaa oppimisen: nyt papukaija tunnistaa tutun sanan ja toistaa repertuaariinsa lisäämänsä lauseen, jossa tuo sana esiintyy. Oliolla on muisti!

Toinen olioesimerkki: radio

Seuraavassa esimerkissä käytämme valmiiksi määriteltyä radio-oliota. Jälleen kerran voit itse kokeilla mukana alla esitettyjä käskyjä ja varioida niitä oman makusi mukaan.

Radio-oliomme mallintaa radion kanavavalitsinta kuvitteellisessa yksinkertaistetussa laitteessa. Sillä on neljä "pikavalintaa", joilla sen voi (virtuaalisesti) kääntää tietylle kanavalle. Tämä onnistuu valitse-metodilla, jolle annetaan parametriksi pikavalinnan numero 1:n ja 4:n väliltä. Otetaan vaikkapa pikavalinta numero kaksi:

radio.valitse(2)res7: String = 94,0 MHz: Radio Suomi

Radio-olio on nyt satuttu määrittelemään niin, että pikavalinta 2 asettaa taajuudeksi 94,0 megahertsiä. valitse-metodin palautusarvo on merkkijono, joka kertoo taajuuden ja sillä soivan kanavan nimen. Muilla parametriarvoilla saadaan muita taajuuksia:

radio.valitse(4)res8: String = 98,5 MHz: Radio Helsinki

virita-metodi "kääntää hertsinapista" eli muuttaa valittua taajuutta parametriksi annetun verran nykyisestä:

radio.virita(2)res9: String = 98,7 MHz: kohinaa

Muutos mitataan "pykälissä". Tällä radiolla yksi pykälä on 100 kHz, joten tässä kasvatettiin taajuutta 2 * 100 kHz aiemmasta. (Sieltä ei löydy kanavaa.)

Huomaa, että radio-olio kykenee pitämään kirjaa omasta taajuudestaan: se määrittää itselleen uuden tilan vanhan tilansa ja saamansa parametriarvon perusteella. Tälläkin oliolla on muisti.

Tietojen kysyminen oliolta

Radio-olioltamme voi pyytää tiettyjä tilatietoja yksinkertaisesti laittamalla pisteen perään tuon ominaisuuden nimen. Voimme kysyä valitun taajuuden ja "pykälän" koon (kilohertseinä):

radio.taajuusKHzres10: Int = 98700
radio.pykalaKHzres11: Int = 100

Nämä kohdat eroavat yllä tehdyistä metodikutsuista sikäli, että näissä ei käytetty parametreja eikä kaarisulkeita.

Olion ominaisuuden muuttaminen sijoittamalla

Radio-oliomme on laadittu niin, että sitä voi komentaa muuttamaan tiettyjä ominaisuuksiaan tutunnäköisellä sijoituskäskyllä. virita- ja valitse-metodeille vaihtoehtoisesti radio-olion viritystaajuuden voi asettaa haluamakseen myös suoralla käskyllä:

radio.taajuusKHz = 92200radio.taajuusKHz: Int = 92200

Tämä on käytännössä hieman toisennäköinen tapa lähettää oliolle viesti: "Aseta taajuusKHz-ominaisuutesi arvoksi 92200."

Animaatio olion käyttämisestä

Anna REPLissä käskyt, joilla valitset radiosta pikavalinnan numero 3 ja sitten virität sen 5 pykälää (eli 500 kHz) isommalle taajuudelle. Mikä on radion taajuus kilohertseinä näiden käskyjen antamisen jälkeen?
Kirjoita tähän sellainen sijoituskäsky, jolla radiomme taajuudeksi saadaan täsmälleen 106200 kHz riippumatta siitä, mikä sen taajuus aiemmin oli:

Olioista ja abstraktioista

Luvun 1.6 lopussa todettiin, että funktiot ja muuttujat ovat ohjelmoinnissa käytettyjä abstraktioita, jotka tekevät ohjelmoinnista käytännöllisempää.

Abstrahointi liittyy olioihin ensisijaisesti kahdella tavalla.

Ensinnäkin kukin olio on abstraktio jostakin mallinnettavasta asiasta. Siihen on valittu tiettyjä piirteitä, jotka ovat laadittavan ohjelman kannalta oleellisia, ja jätetty toisia piirteitä pois.

Toisaalta oliolla itsellään on sekä sisäinen toteutus että "julkisivu", jota käyttäen olion kanssa viestitään. Julkisivu on abstraktio itse oliosta. Siihen kuuluvat muun muassa metodien nimet, parametrien tyypit, palautusarvojen tyypit ja muutenkin kaikki se tieto, mitä olion käyttäjä tarvitsee viestiäkseen onnistuneesti olion kanssa. Metodien toteutusalgoritmit ja olion sisäisen kirjanpidon yksityiskohdat taas eivät kuulu julkisivuun. Tähän aiheeseen palaamme luvussa 3.2.

Lopuksi: olioista ja ohjelman olomuodoista

Koska tämän luvun aihe on niin keskeinen, malta katsoa vielä seuraavakin lyhyt esitys, joka käsittelee aihetta toisesta perspektiivistä ja pohjustaa tulevia lukuja.

Tässä luvussa olet nähnyt esimerkkejä Scala-olioista ja tiedät suunnilleen, miten voit käsitellä ja komentaa oliota, jonka "julkisivun" tunnet. Sotasuunnitelma on tämä:

  • Luvussa 2.2 opit toteuttamaan yksittäisolioita: selviää, miten voit itse määritellä uudenlaisen olion ja tavan, jolla olio reagoi vastaanottamiinsa komentoihin.
  • Luvussa 2.3 tutustut luokkiin eli olioiden tyyppeihin. Niiden avulla voi määritellä ominaisuuksia lukuisille samankaltaisille olioille kerralla. Opit aluksi käyttämään valmiiksi määriteltyjä luokkia Scalalla, ja sitten...
  • ... luvussa 2.4 näet, miten uusia luokkia voi toteuttaa itse ja pääset jo harjoittelemaankin luokkien laatimista.
  • Kakkos-, kolmos- ja neloskierroksilla jatkamme GoodStuff-ohjelmaan tutustumista. Opit tuntemaan luokat, jotka tuon sovelluksen toteuttavat. Rinnalla toki työstämme monia muitakin ohjelmia.
  • Koko loppukurssin ajan opit erilaisia käsitteitä ja tekniikoita, joita voit soveltaa, kun rakennat ohjelmia luokista ja olioista.

Yhteenvetoa

  • Olio-ohjelmointi tarjoaa erään tavan määritellä ohjelman ongelmakenttään liittyviä asioita ja käsitteitä sellaisessa muodossa, joka sopii tietokoneen käsiteltäväksi.
  • Olio on olio-ohjelmoinnissa käytetty kuvaus yhdelle asialle. Olioin voi kuvata mitä erilaisimpia asioita.
    • Tyypillisellä oliolla on sekä ominaisuuksia, jotka ovat osa sen tilaa, että toimintoja eli metodeita, jotka määräävät, mitä oliolla voi tehdä.
    • Kun tietokone suorittaa olio-ohjelmaa, olioiden tiedot pidetään tallessa koneen muistissa. Niistä muodostuu ohjelman tila.
  • Oliota voi komentaa kutsumalla sen metodeita. Metodit ovat olioihin liitettyjä funktioita, joilla käsitellään olioon liittyviä tietoja ja muutenkin hoidetaan olion vastuualueelle kuuluvia asioita.
  • Olio-ohjelman suorituksen päävaiheet muodostuvat olioiden välisestä viestinnästä.
    • Oliot voi määritellä "komentamaan" toisiaan. Ne viestivät kutsumalla toistensa metodeita. Olio voi delegoida osan tehtävästä toiselle oliolle.
    • Pohjimmiltaan olio-ohjelmankin ajo on tietokoneen suorittama käskysarja. Käsitteellinen mallinnus olioina jäsentää ongelmakentän; olioiden välinen viestintä määrää, missä järjestyksessä ohjelmakoodi suoritetaan.
  • Scalan metodikutsut toimivat kuin muutkin funktiokutsut:
    • Eteen laitetaan kohdeolion osoittava lauseke ja piste: olio.metodi(parametrit)
    • Joillakin olioilla on ominaisuuksia, joita voi muuttaa myös sijoituskäskyillä: olio.ominaisuus = uusiArvo.
  • Lukuun liittyviä termejä sanastosivulla: olio-ohjelmointi, olio, metodi; abstraktio; aihealue eli domain; tila; staattinen, dynaaminen; yksittäisolio.

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!

Materiaalin luvut tehtävineen ja viikkokoosteineen on laatinut Juha Sorva.

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 suunnittelivat Juha Sorva ja Teemu Sirkiä. Teemu Sirkiä ja Riku Autio toteuttivat ne apunaan Teemun aiemmin rakentamat työkalut Jsvee- ja Kelmu.

Muut diagrammit ja materiaaliin upotetut vuorovaikutteiset esitykset laati Juha Sorva.

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

Tapa, jolla 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+ luotiin alun perin Aallon LeTech-tutkimusryhmässä pitkälti opiskelijavoimin. Nykyään tätä avoimen lähdekoodin projektia kehittää Tietotekniikan laitoksen opetusteknologiatiimi ja tarjoaa palveluna laitoksen IT-tuki. Pääkehittäjänä on tällä hetkellä Markku Riekkinen, jonka lisäksi A+:aa ovat kehittäneet kymmenet Aallon opiskelijat ja muut.

A+ Courses -lisäosa, joka tukee A+:aa ja O1-kurssia IntelliJ-ohjelmointiympäristössä, on toinen avoin projekti. Sen ovat luoneet Nikolai Denissov, Olli Kiljunen, Nikolas Drosdek, Styliani Tsovou, Jaakko Närhi ja Paweł Stróżański yhteistyössä Juha Sorvan, Otto Seppälän, Arto Hellaksen ja muiden kanssa.

Kurssin tämänhetkinen henkilökunta löytyy luvusta 1.1.

Joidenkin lukujen lopuissa on lukukohtaisia lisäyksiä tähän tekijäluetteloon.

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