Helsingin yliopisto / Tietojenkäsittelytieteen laitos / 581258-1 Johdatus ohjelmointiin
Copyright © 1998 Arto Wikla. Tämän oppimateriaalin käyttö on sallittu vain yksityishenkilöille opiskelutarkoituksissa. Materiaalin käyttö muihin tarkoituksiin, kuten kaupallisilla tai muilla kursseilla, on kielletty.

4.1 Käsitteet ja idea

(Muutettu viimeksi 16.11.1998)

Luku 4.1 on yleiskatsaus olio-ohjelmoinnin perusideoihin. Teknisemmin ja tarkemmin asiat asiat käsitellään muissa luvun 4 aliluvuissa.

Olio-ohjelmointi

Perinteinen proseduraalinen ohjelmointi (Pascal, C, ...), voidaan nähdä "reseptin" antamisena ongelman ratkaisuksi. Algoritmi on tuo resepti. Ongelman jäsentämiseen voidaan käyttää ns. rakenteisen ohjelmoinnin menetelmiä, vaikkapa ns. asteittaista tarkentamista. Koko ohjelmasta muodostuu ongelman ratkaisemisen toiminnallinen kuvaus: "ensin tehdään sitä, sitten tätä, ..."

Olio-ohjelmoinnin perusajatus on ongelmakentän - sovellusalueen - kuvaaminen olioina, olioiden ominaisuuksina ja toimintoina sekä olioiden välisinä suhteina. Sovellusalueen käsitteet ja toimijat mallinnetaan olioina. Koska nuo käsitteet ja toimijat ovat usein pysyvämpiä kuin yksittäiset tiedonkäsittelytarpeet, olioiden rakenteen ja toiminnan voi olettaa säilyvän vaikka yksittäisen sovelluksen rakennetta muutetaan tai kun luodaan kokonaan uusia sovelluksia.

Olio-ohjelmoinnin voi nähdä myös teknisemmin: ohjelmointiongelma jaetaan uudella tavalla osaongelmiksi: olioiden rakenne ja toiminnallisuus ohjelmoidaan erikseen, kunkin erityisen sovelluksen rakenne erikseen. Muutokset sovelluksessa tai yksittäisen olion toteutustavassa eivät vaikuta ratkaisun muihin osiin.

Kunnolla suunniteltuja olioita pitäisi voida käyttää sellaisinaan yhä uusien erityisten ongelmien ratkaisemiseen, ohjelmistojen ylläpidettävyyden ja hallinnan pitäisi helpottua...

Luokat ja oliot

Luokka (class) on olio-ohjelmoinnin peruskäsite: metodeita ja siis algoritmeja voi kirjoittaa vain luokkaan, muuttujia voi määritellä vain joko jossakin luokassa tai jonkin luokan sisältämässä metodissa. Jokainen olio (object) on jonkin luokan ilmentymä (instance). Luokka määrittelee olion rakenteen ja käyttäytymisen.

Olioajattelu voidaan nähdä mallintamisena, jossa luokka vastaa jotakin yleiskäsitettä. Esimerkiksi luokka Eläin voisi olla eläimen malli, jossa on määritelty kaikille eläimille yhteisiä ominaisuuksia (paino, ikä, ...) ja toimintoja (syöminen, lisääntyminen, ...):

    public class Elain {
      private int paino;
      ...
      public Elain(...) { ...
      ...
      public void syö(...) { ...
      ...
    }

Luokan ilmentymä on jokin erityinen olio, joka kuuluu tuohon luokkaan. Esimerkiksi erityinen kissaolio nimeltään Missu voisi kuulua luokkaan Eläin. Oliolla Missu on tällöin jokin erityinen paino, joka luultavasti muuttuu, kun Missu syö, jne.

Luokalla voi olla aliluokkia (subclass), jotka erikoistavat ja rajaavat luokkaa: aliluokka perii (inherit) yliluokkansa (superclass) ominaisuudet ja toiminnot sekä täydentää niitä erityisemmillä.

Luokalla Eläin voisi olla esimerkiksi aliluokka Kissa, joka täydentää luokan Eläin ominaisuuksia erityisillä kissaominaisuuksilla, vaikkapa naukumistiheydellä ja toimintoja vaikkapa kehräämisellä:

     public class Kissa extends Elain {
       ...
       int naukumistiheys;
       ...
       public Kissa(...) { ...
         ...
       public void kehrää(...) { ...
       ...
     }
Kun Missu nyt luotaisiinkin Kissan ilmentymäksi, sillä olisi sekä Eläimen että Kissan määräämät ominaisuudet. Eläimenä Missu voi vaikkapa syödä, Kissana kehrätä.

Hieman konkreettisempi tapa nähdä luokat ja olioit on ns. abstraktin tietotyypin idea. Siinä tietorakenteen toteutus ja käyttö eristetään toisistaan. Tietorakenteen käyttäjä tuntee vain operaatioita, joilla (hänelle abstraktin!) tietorakenteen tilaa muutetaan ja kysytään. Tietorakenteen toteuttaja puolestaan ei ota kantaa siihen, mihin tietorakennetta käytetään. Käyttäjää ja toteuttajaa yhdistää pelkästään sopimus siitä, mitä operaatiot (abstraktissa) tietorakenteessa saavat aikaan. Tietorakenteen toteutuksen piilottamista kutsutaan kapseloinniksi.

Abstraktin tietotyypin voi rakentaa olio-ohjelmoinnin välinein seuraavasti

Esimerkki tästä tavasta käyttää luokkia oli luvun 2.6 luokka PikkuVarasto.

Luokka on Java-kielessä hyvin joustava väline: sitä voi käyttää myös ns. tietueen (record, struct) tapaan, sillä voi toteuttaa aliohjelmakirjaston, sovelluksen pääohjelma esitetään jonkin luokan erityisenä main-metodina, WWW-sivulle liitettävä sovelma toteutetaan luokkana, ...

Luokka muodostuu kentistä (field) eli attribuuteista eli muuttujista ja metodeista eli operaatioista. Kentät esittävät luokan ilmentymän (tai itse luokan!) tilaa (state). Metodeilla tilaa tutkitaan ja muutetaan.

Kenttien ja metodien näkyvyyttä (scope) (on käytettävissä kaikkialla, on käytettävissä vain luokassa, ...) ja olemassaoloa (liittyy olioon, liittyy itse luokkaan) säätelemällä voi laatia noita edellä lueteltuja hyvin erilaisia ohjelmointivälineitä. Myös luokan oma näkyvyys on säädettävissä.

Pakkaus

Kun ohjelman/ohjelmiston koko kasvaa ja tekijöitä on ehkä useampia, luokkien ja metodien nimistä voi tulla ongelmia: sama nimi yritetään antaa eri luokille, "kaikki hyvät nimet ovat jo käytössä", "minne mikin väline on tullut säilöttyä?", ...

Javassa luokkia voi liittää yhteen ns. pakkauksiksi (package), joihin on tapana kerätä toisiinsa tavalla tai toisella liittyviä luokkia. Pakkaus muodostaa "nimiavaruuden", jolla nimien näkyvyyttä voi säädellä. Pakkauksen välineet otetaan käyttöön ns. import-määreellä. Javan monet valmiit luokkakokoelmat on toteutettu pakkauksina: java.lang, java.util, java.io, ... (Pakkaus on ohjelmatiedostojen hallinnan väline. Se ei sinänsä liity olio-ohjelmointiin!)


Kiitos tämän kappaleen eläimellisen mainion esimerkin ideasta sekä erittäin hyödyllisistä neuvoista ja kommenteista Tomi Silanderille!
Takaisin luvun 4 sisällysluetteloon.