Olio (ohjelmointi)

**Olio** on olio-ohjelmoinnissa tietokoneohjelman perusyksikkö, joka sisältää joukon loogisesti yhteenkuuluvaa tietoa (attribuutteja) ja toiminnallisuutta (jäsenfunktioita eli metodeja). Oliot voivat kommunikoida keskenään lähettämällä viestejä tai kutsumalla toisen olioiden metodeja. Viestin vastaanottaminen suorittaa määritellyn toiminnon vastaanottavassa oliossa. Oliota käytetään ohjelmistosuunnittelussa esittämään jonkin abstraktin tai reaalimaailman käsitteen ilmentymää ohjelmistossa. Oliokielillä laaditut ohjelmat koostuvat tavallisesti lukuisista olioista, joiden yhteistyön tuloksena on ratkaisu ohjelmointiongelmaan. 

Oliolla on määritelmä, josta käytetään nimeä luokka. Luokka määrittelee jonkun tietyn oliojoukon yhteiset piirteet. Olio luodaan laatimalla luokan ilmentymä eli *[[Instanssi (ohjelmointi)|instanssi]]*, esimerkiksi varaamalla olion vaatima muisti. Esimerkiksi henkilörekisteriohjelmassa voidaan määritellä luokka *Henkilö*, joka määrittelee millaista tietoa henkilöistä halutaan esittää ja millä tavalla näitä tietoja voidaan käsitellä. Ohjelman ajon aikana luokasta *Henkilö* luodaan olioita esittämään yksittäisiä henkilöitä. 

Oliokielissä oliot toteutetaan ajonaikaisina tietorakenteina, jotka sisältävät jäsenmuuttujat olion tiedon tallentamiseen. Olioiden toiminnallisuus määritellään useimmiten luokkien jäsenfunktioissa, jolloin kaikki saman luokan oliot sisältävät täsmälleen saman toiminnallisuuden tiedon käsittelyyn. Oliokieli osaa selvittää olion määrittelevän luokan, eli tyypin, ja siten käyttää oikeita jäsenfunktioita eri olioiden yhteydessä. Oikean jäsenfunktion löytämiseen on kaksi keinoa. Joko kääntäjä voi tehdä sen käännöksen yhteydessä, jolloin puhutaan staattisesta sidonnasta, tai se tapahtuu ajonaikana, jolloin kyseessä on dynaaminen sidonta.

Yksi varhaisimmista oliokielistä, 1960-luvulla kehitetty Simula esitteli luokan, olion, perinnän ja dynaamisen sidonnan käsitteet.
Toisen koulukunnan luoja on ollut Smalltalk. Näiden kahden suunnan ohjelmointikielissä käytetään toisistaan eriävää termistöä. Simulasta oliomallinsa lainanneessa C++:ssa kutsutaan luokan jäsenfunktioita, Smalltalkin jälkeläisissä kuten Objective-C:ssä niille lähetetään viestejä. Smalltalkiin perustuvissa kielissä käytetään dynaamista sidontaa, kun taas Simulaan perustuvissa kielissä suorituskykysyistä staattista silloin kun se on mahdollista.

## Yleisimpiä suunnittelumalleja objekteille
Tärkeä käsite objekteille on suunnittelumalli (design pattern). Suunnittelumalli tarjoaa uudelleenkäytettävän mallin yleisen ongelman ratkaisemiseksi. Seuraavat oliokuvaus-esimerkit ovat joitain yleisimpiä suunnittelumalleja objekteille: 

* Funktio-olio (Function object) on olio, jossa on yksi ainoa metodi (C++:ssa tätä metodia kutsutaan funktio-operaattoriksi "operator()"), joka toimii paljon kuin funktio (kuten C/C++:n funktiopointeri). 
* Muuttumaton olio (Immutable object) on olio, jonka tila asetetaan luomishetkellä kiinteäksi ja joka ei sen jälkeen muutu.  
* Ensimmäisen luokan olio (First-class object) on olio, jota voidaan käyttää ilman rajoituksia. 
* Säilö-olio (Container object): olio, joka voi sisältää muita objekteja. 
* Tehdasolio (Factory object): olio, jonka tarkoitus on luoda muita objekteja. 
* Metarakenne (Metaobject): olio, jonka avulla voidaan luoda muita objekteja (vertaa luokkaan, joka ei välttämättä ole olio). 
* Prototyyppiolio (Prototype object): erikoistunut metarakenne, josta muita objekteja voidaan luoda kopioimalla. 
* Jumalaolio (God object): olio, joka tietää tai tekee liian paljon (esimerkki anti-mallista). 
* Yksittäisinstanssiolio (Singleton object): olio, joka on sen luokan ainoa instanssi ohjelman suorituksen aikana. 
* Suodatinolio (Filter object): olio, joka vastaanottaa datavirran syötteenään ja muuntaa sen olion lähtöön. Usein syöte- ja lähtövirrat ovat merkkijonovirtoja, mutta ne voivat olla myös mielivaltaisia oliovirtoja. Nämä ovat yleensä käytössä kääreissä, koska ne peittävät olemassa olevan toteutuksen abstraktiolla, joka vaaditaan kehittäjän puolelta.         

## Periytyminen
Olio-ohjelmoinnissa periytyminen on yksi keskeisimmistä elementeistä. Periytymisessä on luokan piirteiden siirtymistä toiselle luokalle säilyttäen samanlaisen toteutuksen. Kyseessä on siis periaate siitä, että yleisempi määrittely on voimassa periytyneissä objekteissa tai luokissa. Perinnän idea on lukkien organisointi hierarkkisiin periytymispuihin, jossa lapsiluokkaa perii vanhempiensa tiedon ja toiminnallisuuden. Periytymisessä ominaisuuksia saavaa luokkaa nimitetään aliluokaksi ja puolestaan antavaa luokkaa yliluokaksi. Toisin sanoen yliluokalla viitataan luokan periytymishierarkiassa ylemmän tason luokkiin, kuten kantaluokkaan ja kantaluokan kantaluokkaan. Yliluokat toimivat olio-ohjelmoinnissa perustana aliluokille ja tarjoavat niille yhteisiä ominaisuuksia ja toiminnallisuuksia.

### Periytymistyypit
Erilaisia periytymistyyppejä:

* **Yksittäinen periytyminen**: lapsiluokka perii yhden tiedot ja ominaisuudet yhdeltä vanhemmalta. **A → B**
* **Moniperiytyminen**: yksi lapsiluokka perii useammalta vanhemmalta ominaisuuksia. **A & B → C**
* **Monitasoinen periytyminen**: lapsiluokka johdetaan toisesta lapsiluokasta. **A → B → C**

### Näkyvyysmääreet
Näkyvyysmääreet ovat olio-ohjelmoinnissa keskeisiä tekijöitä, jotka määrittävät luokan jäsenien näkyvyyden muille. Näkyvyysmääreet voidaan luokitella seuraavasti:

* **Private**: Kaikkein rajoittavin näkyvyysmääre, joka luokan jäsenten käytön vain luokan sisälle. Private-jäseniä ei voida käyttää muissa luokissa.
* **Package**: Oletusarvoinen näkyvyysmääre. Jäsenet näkyvät paketin sisällä, mutta ulkopuolisista luokista ei pääse käyttämään tällä määreellä merkittyjä luokkia.
* **Public**: Julkinen rajapinta. Luokan jäsenet ovat julkisia, joita kaikki voivat käyttää.
* **Protected**: Käytetään perittäessä luokkia. Sallii lapsiluokkien käyttämisen yläluokan jäseniä.

## Jaetut oliot
Oliolähtöinen lähestymistapa ei ole ainoastaan ohjelmointimalli. Sitä voidaan käyttää yhtä hyvin rajapinnan määrittelykielenä jaetuille järjestelmille. Jaetun laskentamallin oliot ovat yleensä suurempirakenteisia, pitkäkestoisempia ja palvelulähtöisempiä kuin muut ohjelmoinnin oliot.  

Vakiomenetelmä jaettujen olioiden paketoimiseksi on Interface Definition Language (IDL) -käyttöliittymän kautta. IDL suojaa asiakkaan kaikilta jaetun palvelinolion yksityiskohdilta. Nämä yksityiskohdat voivat olla esimerkiksi millä tietokoneella olio sijaitsee tai mitä ohjelmointikieltä tai käyttöjärjestelmää se käyttää. IDL on myös yleensä osa jaettua ympäristöä, joka tarjoaa palveluja, kuten transaktioita ja jatkuvuutta kaikille objekteille yhtenäisellä tavalla. Kaksi suosituinta jaettujen olioiden standardia ovat Object Management Groupin CORBA-standardi ja Microsoftin DCOM. 

Jaettujen olioiden lisäksi on ehdotettu useita muita laajennuksia peruskäsitteeseen, jotta jaettu tietojenkäsittely olisi mahdollista: 

* Protokollaoliot (Protocol object)s ovat osa protokollapinoa, joka sulkee verkkokommunikaation oliopainoitteiseen rajapintaan.  
* Replikoidut oliot (Replicated objects) ovat jaettujen olioiden ryhmiä (niin kutsuttuja replikaatioita), jotka käyttävät jaettua monipuolueprotokollaa saavuttaakseen korkean johdonmukaisuuden omien valtioidensa välillä ja jotka vastaavat pyyntöihin koordinoidusti. Esimerkkeinä voidaan mainita vikaa sietävät CORBA-oliot.  
* Live-jaetut oliot (Live distributed objects) tai yksinkertaisesti elävät oliot, yleistävät kopioidun olion konseptin eri replikaattiryhmiin. Nämä ryhmät saattavat käyttää mitä tahansa jaettua protokolla voiden aiheuttaa vain heikon johdonmukaisuuden paikallisten osavaltioiden välillä.  

Osa näistä laajennuksista, kuten jaetut oliot ja protokollaoliot, ovat verkkoaluekohtaisia termejä erilaisille “tavallisille” objekteille, joita käytetään tietyssä yhteydessä. Toiset, kuten replikoidut oliot ja live-jaetut oliot, ovat epänormaaleja, koska ne hylkäävät tavanomaisen tapauksen, jossa olio sijaitsee yhdellä paikalla kerrallaan. Ne myöskin soveltavat konseptia sellaisiin kokonaisuuksiin (replikaatteihin), jotka saattavat ulottua useisiin sijainteihin saattavat olla vain heikosti johdonmukaisia ja joiden jäsenyys voi muuttua dynaamisesti.  

## Semanttinen web
Semanttinen web on käytännössä hajautettujen objektien kehys. Kaksi keskeistä tekniikkaa semanttisessa webissä ovat Web Ontology Language (OWL) ja Resource Description Framework (RDF). RDF mahdollistaa perusobjektien, kuten nimien, ominaisuuksien, attribuuttien ja suhteiden määrittämisen, jotka ovat saatavilla internetin kautta. OWL lisää rikkaamman objektimallin, joka perustuu joukko-oppiin ja joka tarjoaa lisää mallinnusmahdollisuuksia, kuten moniperintöisyyden.

OWL-objektit eivät ole samanlaisia kuin standardit, suurikokoiset hajautetut objektit, joihin päästään Interface Definition Language -ohjelman avulla. Tällainen lähestymistapa ei sovellu internetille, koska internet muuttuu jatkuvasti, eikä standardointi yhdelle rajapintajoukolle ole helppoa. OWL-objektit ovat yleensä samankaltaisia kuin ohjelmointikielien, kuten Javan ja C++, sovellusalueiden määritysmalleissa käytettävät objektit.

OWL-objektien ja perinteisten objektipohjaisten ohjelmointiobjektien välillä on kuitenkin tärkeitä eroja. Perinteiset objektit käännetään staattisiin hierarkioihin yleensä yksiperintöisyydellä, mutta OWL-objektit ovat dynaamisia. OWL-objekti voi muuttaa rakennettaan suoritusaikana ja tulla uuden tai erilaisen luokan ilmentymäksi.

Toinen tärkeä ero on mallin tapa käsitellä tietoa, joka ei ole tällä hetkellä järjestelmässä. Ohjelmointiobjektit ja useimmat tietokantajärjestelmät käyttävät "suljetun maailman oletusta". Jos tosiasiaa ei tunneta järjestelmässä, se oletetaan vääräksi. Semanttisessa webissä käytetään avointa maailman oletusta: lausuntoa pidetään vääränä vain, jos on todellista asiaankuuluvaa tietoa, että se on väärä, muuten sitä pidetään tuntemattomana, ei totuutena eikä myöskään vääränä.

OWL-objektit ovat itse asiassa eniten samankaltaisia kuin tekoälykehysten, kuten KL-ONE:n ja Loomin objektit.

## Polymorfismi
Polymorfismi on yksi keskeisimmistä käsitteistä olio-ohjelmoinnissa. Se tarkoittaa sitä, että saman nimiset metodit tai funktiot voivat toimia eri tavalla eri objekteille. Polymorfismi mahdollistaa koodin uudelleenkäytön ja tekee siitä modulaarisempaa.

Polymorfismi perustuu periytyvyyteen, joka on toinen tärkeä olio-ohjelmoinnin käsite. Periytyvyys tarkoittaa sitä, että luokka voi periä toiselta luokalta sen ominaisuuksia ja metodeja. Periytyvyyden avulla voidaan väittää saman koodin kirjoittamista uudelleen ja useaan kertaan ja tehdä koodista modulaarisempaa ja helpommin ylläpidettävää.

Polymorfismi toteutetaan usein abstraktien luokkien tai rajapintojen avulla. Abstrakti luokka on luokka, jolla on yksi tai useampi abstrakti metodi. Abstrakti metodi on metodi, joka ei ole toteutettu kyseisessä luokassa, vaan sen toteutus jätetään sen aliluokkien vastuulle. Rajapinta on taas määrittely siitä, mitä metodeja luokka toteuttaa. Rajapinta ei toteuta mitään metodeja itse, vaan sen aliluokat toteuttavat rajapinnan metodit.

Polymorfismi on tärkeä käsite myös dynaamisissa ohjelmointikielissä, kuten Pythonissa ja JavaScriptissä. Näissä kielissä tyypit päätellään automaattisesti suorituksen aikana, mikä mahdollistaa eri tyyppisten objektien käytön samassa koodissa.

Polymorfismi on siis keskeinen käsite olio-ohjelmoinnissa, joka mahdollistaa koodin uudelleenkäytön ja tekee siitä modulaarisempaa ja helpommin ylläpidettävää. Se perustuu periytyvyyteen ja toteutetaan usein abstraktien luokkien tai rajapintojen avulla. Polymorfismi on tärkeä myös dynaamisissa ohjelmointikielissä, joissa se mahdollistaa eri tyyppisten objektien käytön samassa koodissa.

## Olio-ohjelmointia tukevat kielet
Simula (1967) on yleisesti pidetty ensimmäisenä kielenä, jolla on ensisijaiset ominaisuudet objektiperustaisesta ohjelmoinnista. Se luotiin simulaatio ohjelmien tekemiseen, joita myöhemmin alettiin kutsumaan olioiksi. Smalltalk (1972–1980) on toinen esimerkki varhaisesta kielestä, jolla suuri osa OOP-teoriasta kehitettiin. Olio-ohjelmoinnin suhteen voidaan havaita seuraavia eroavaisuuksia:

* Kieliä, joita kutsutaan "puhtaiksi" olio-ohjelmointi kieliksi, koska kaikkea niissä käsitellään johdonmukaisesti olioina, perusteista, kuten merkeistä ja välimerkeistä asti kaikkiin luokkiin, prototyyppeihin, lohkoihin, moduuleihin jne. Ne on suunniteltu erityisesti helpottamaan ja jopa pakottamaan olio-ohjelmoinnin metodeja. Esimerkkejä: Ruby, Scala, Smalltalk, Eiffel, Emerald, JADE, Self, Raku.
* Kieliä, jotka on suunniteltu pääasiassa olio-ohjelmointiin, mutta jotka sisältävät joitakin proseduraalisia elementtejä. Esimerkkejä: Java, Python, C++, C#, Delphi / Object Pascal, VB.NET.
* Kieliä, jotka ovat historiallisesti proseduraalisia kieliä, mutta joihin ollaan laajennettu joitakin olio-ohjelmoinnin ominaisuuksia. Esimerkkejä: PHP, Perl, Visual Basic (johdettu BASIC-kielestä), MATLAB, COBOL 2002, Fortran 2003, ABAP, Ada 95, Pascal.
* Kieliä, jotka sisältävät suurimman osan olion ominaisuuksista (luokat, metodit, periytyvyys), mutta erityisellä alkuperäisellä muodollaan. Esimerkkejä: Oberon (Oberon-1 tai Oberon-2).
* Kieliä, joissa on abstraktien tietotyyppien tuki, joka voi vaikuttaa olio-ohjelmoinnin mukaiselta, mutta ilman kaikkia olio-ohjelmoinnin ominaisuuksia. Tämä sisältää oliopohjaiset ja prototyyppipohjaiset kielet. Esimerkkejä: JavaScript, Lua, Modula-2, CLU.
* Chameleon-ohjelmointikieliä, jotka tukevat useita paradigmoja, mukaan lukien olio-ohjelmointi. Tcl erottuu näiden joukosta TclOO: n ansiosta, hybridimallinen objektijärjestelmä, joka tukee sekä prototyyppipohjaista ohjelmointia että luokkapohjaista olio-ohjelmonita.

## Lähteet