Peruskäsitteitä: kapselointi (encapsulation)

Kapselointi

Terminä kapselointia käytetään ohjelmoinnin yhteydessä kahdessa merkityksessä: tiedon ja käyttäytymisen sitomista yhteen yksikköön eli olioon sekä tiedon piilottamiseen olion sisäisin muuttujiin. Tällä "piilottamisella" pyritään estämään ohjelman virhetilanteita, koska tällöin olion muuttujiin ei pääse suoraan luokan ulkopuolelta käsiksi. Olion käyttäjän ei tarvitse tietää miten olio sisäisesti toimii, vaan riittää tietää miten oliota käytetään. Tämä käyttäminen tapahtuu olion julkisen rajapinnan eli olion toimintojen kautta. Olion tila suojataan käyttämällä eri suojamääreitä, olion täytyy pystyä puolustamaan itseään.

Kuvitellaan alla olevaa tilannetta, jossa Car-luokassa on olemassa Speed-ominaisuus. Car-oliolle on myös määritelty sen maksiminopeutta kuvaava ominaisuus MaxSpeed, jonka arvo on 200. Toisin sanoen Car-luokan toteuttavien autojen maksiminopeuden tulisi olla 200.


    

Car-luokasta voidaan luoda olio ja käyttää sen speed-ominaisuutta seuraavasti:


    

Edellä olevassa tilanteessa mikään ei estä car-olion Speed-ominaisuuden käyttämistä, vaan sille voidaan alustaa mitä tahansa arvoja muista ohjelmakokonaisuuksista. Toisin sanoen olion tila saadaan rikottua ja ohjelma ei toimi siten kuin ohjelmoija olisi sen halunnut toimivan.

Pelisäännöt

1. ohjelmoija antaa tekemästään luokasta tiedon, miten oliota voidaan käyttää julkisten (public) metodien kautta
2. ohjelmoija pitää luokan ominaisuudet suojattuna (private)

check_circle Olion ominaisuuksiin ei päästetä suoraan käsiksi, vaan toimintojen kautta. Tällöin voidaan estää vääränlaiset olion tilan muutokset toimintojen avulla.
check_circle C# mahdollistaa myös aksessorien käytön, jolla voidaan rajata luokan ominaisuuksien käyttämistä. <- tärkeä tämän kurssin kannalta!

Olion ominaisuuksien ja toimintojen suojaaminen

Olion tila eli sen ominaisuudet ja toiminnot voidaan suojata erilaisilla suojamääreillä. Suojamääreillä on erilaisia tasoja, joiden mukaisesti suojaus määräytyy.

Public ominaisuus ja/tai toiminto on saavutettavissa kaikkialta
Privateominaisuus ja/tai toiminto on saavutettavissa vain saman luokan sisällä
Protectedominaisuus ja/tai toiminto on saavutettavissa vain saman luokan tai aliluokan sisällä
Internalominaisuus ja/tai toiminto on saavutettavissa saman assemblyn luokista
Protected internalominaisuus ja/tai toiminto on saavutettavissa saman assemblyn luokista ja toisesta assemplysta luokan toteuttavasta aliluokasta

Esimerkki: Olion tilan suojaaminen get- ja set-aksessoreilla

Olion ominaisuuksia voidaan säädellä käyttämällä aksessoreita. Aksessoreita on olemassa get- ja set-tyyppisiä. get-aksessorilla luetaan ominaisuuden arvo ja set-aksessorilla ominaisuuteen voidaan tallentaa uusi arvo. get-aksessorin tulee päättyä aina return-lauseeseen, jossa palautetaan sitä vastaavan kentän arvo. set-aksessori ei palauta koskaan mitään, mutta saa aina parametrina value-muuttujan, joka sisältää vastaavaan kenttään tallennettavan arvon. Olion tilan suojaamisen kannalta on tärkeää, että set-aksessorissa toteutetaan tallennettavan arvon eheystarkistukset. Aksessoreita käytettäessä tulee luokkaan määritellä myös varsinainen ominaisuus, joka on aina julkinen.

Huom! Tekemällä ainoastaan get-aksessorin, ominaisuus on "read-only"-tilassa (vastaavast pelkkä set-aksessori, ominaisuus on "write-only"-tilassa).

Seuraavassa esimerkissä suojataan aikaisemmin esitetty car-olion tila käyttämällä private-suojamäärettä ja aksessoreita. Tässä tapauksessa olion ominaisuuksia voidaan käyttää kuten ne olisivat julkisia (eli suoraan olio.notaation-kautta), mutta todellisuudessa käytetään olion get- ja set-aksessoreita. Tällöin set-aksessorissa voidaan tarkistaan onko haluttu olion tilan muutos sallittu vai ei.


    

Nyt Car-luokassa määritelty speed-ominaisuus on private-suojattu eli sen arvoa ei pääse mistään luokan ulkopuolelta suoraan muuttamaan. Luokka tarjoaa kuitenkin aksessorien kautta Speed-ominaisuuden, jossa set-aksessorissa tarkistetaan, että haluttu speed-arvo on sallittu.

Tällöin Car-luokkaa voidaan käytetään sen ominaisuuksien kautta suoraan, esim. pääohjelmasta:


    
    

Auto-Implemented ominaisuudet (Properties)

C# 3.0 -version myötä käytössä on myös ns. "Auto-Implement" -ominaisuudet, jotka lyhentävät edellä esitettyjen ominaisuuksien kirjoittamista, jos mitään erityistä logiikkaa ominaisuuden alustamiselle tai palauttamiselle ei haluta. Tällöin ominaisuus voidaan kuvata alla olevalla tavalla.


    
    

UML ja suojamääreet

UML-luokkakaavioiden kuvaamisessa suojamääreillä on erityiset merkinnät. Public (+), Private (-), Package (~) ja Protected (#).

Yhteenveto

Tämä on erittäin tärkeä asia olio-ohjelmoinnissa. Olio-ohjelmointia käytetään erittäin paljon maailmanlaajuisesti mm. erilaisissa laitteissa, tuotantoprosessien ohjauksessa yms..., joissa luotettavuus ja erilaiset raja-arvot ovat erittäin tärkeitä. Näin ollen ohjelmoijan on suojattava omat kokonaisuutensa, ettei niitä käytetä väärin!