Olio-ohjelmointi (, OOP) on ohjelmoinnin ohjelmointiparadigma, jossa ohjelmointiongelmien ratkaisut jäsennetään olioiden yhteistoimintana.
Oliot sisältävät niiden oman sisäisen tilan (kapselointi) sekä julkisen rajapinnan. Olio-ohjelmointi voi olla: luokkapohjaista: oliot saavat tilan ja toiminnallisuuden luokan jäsenien mukaan prototyyppipohjaista: oliot saavat toiminnallisuuden prototyyppioliolta
Luokkapohjaisessa ohjelmoinnissa luokat määritellään etukäteen ja oliot luodaan näiden luokkien perusteella, jolloin oliot saavat tilan ja toiminnallisuuden luokan jäsenten mukaan. Esimerkiksi jos kaksi oliota, kuten kissa ja koira, toteutetaan luokasta Eläin, niin ne ovat luonnollisesti eläimiä ja niitä voidaan käsitellä samalla tavalla. Tämä tarkoittaa sitä, että näillä eläinolioilla on samat ominaisuudet.
Prototyyppipohjaisessa olio-ohjelmoinnissa oliot saavat toiminnallisuuden ja ominaisuudet prototyyppioliolta eikä luokkia ole edes olemassa. Olion prototyyppi on vain toinen olio, johon olio on linkitetty. Jokaisella oliolla on vain yksi prototyyppilinkki. Uusia olioita voidaan luoda niiden prototyypeiksi valittujen jo olemassa olevien olioiden perusteella. Kahta eri oliota, kissa ja koira, voi kutsua eläimiksi, jos eläinolio on olemassa ja se on sekä kissan että koiran prototyyppi. Voidaan sanoa eläinluokan olevan saman prototyypin jakavien olioiden ekvivalenssiluokka. Prototyypin ominaisuudet ja metodit delegoituvat kaikille tämän prototyypin määrittämän ekvivalenssiluokan olioille. Olion omistamia yksilöllisiä ominaisuuksia ja metodeja ei saa jakaa muiden saman ekvivalenssiluokan olioiden kanssa. Prototyypin kautta voidaan toteuttaa vain yksi perimä, joka tapahtuu prototyypin kautta.
Olio-ohjelma muodostuu kokoelmasta yhteistyössä toimivia olioita, kun taas perinteinen proseduraalinen tietokoneohjelma on lista suoritettavia ohjeita tietokoneelle.
Olio-ohjelmoinnissa tieto ja sitä käsittelevä toiminnallisuus tyypillisesti kootaan yhteen tietorakenteeksi, jota kutsutaan olioksi. Olio käsittelee sisältämäänsä tietoa ja voi vastaanottaa viestejä ja lähettää tietoa muille olioille. Jokainen olio voidaan nähdä itsenäisenä pienenä koneena, jolla on tietty rooli tai vastuu.
Olio-ohjelmointi on kehitetty helpottamaan ja selkeyttämään yhä monimutkaisemmiksi tullutta ohjelmistojen kehittämistä ja ylläpitoa. Olio-ohjelmoinnin yhtenä tavoitteena on tehdä ohjelmistojen laajentamisesta ja ylläpidosta helpompaa. Yksittäinen olio vastaa jostakin itsenäisestä osa-alueesta ohjelman kokonaisuudessa. Olio on merkityksellinen myös irrotettuna välittömästä asiayhteydestään, jolloin sitä voidaan käyttää myös uusissa asiayhteyksissä. Oliota käyttävän tarvitsee vain tietää, mihin tarkoitukseen olio on suunniteltu ja miten sitä pitää käyttää. Koska yhden pienen olion sisäinen ohjelmakoodi on lyhyt, se on yleensä helpommin ymmärrettävissä ja ylläpidettävissä.
Tietokoneohjelmat voivat hyödyntää olioita monella tapaa. Puhtaissa oliokielissä kaikki kielen alkiot ovat olioita. Useat ohjelmointikielet, kuten C++ sallivat olioiden käyttämisen yhdessä perinteisen ohjelmointimallin sisällä. Oikein käytettynä olio-ohjelmointi nopeuttaa kehitystyötä, vähentää redundanssia, ohjelmointivirheitä ja helpottaa merkittävästi ohjelmistojen ylläpitoa. Nykyaikaisten tietokoneohjelmien kehittämisessä olio-ohjelmointi on yksi tärkeimmistä työkaluista. Suosittuja olio-ohjelmointia tukevia kieliä ovat muun muassa C++, C#, Java, Python ja Visual Basic.
Merkittäviä oliokieliä ovat: Ada, ActionScript, C++, Common Lisp, C#, Dart, Eiffel, Haxe, Java, JavaScript, Kotlin, logo, MATLAB, Objective-C, Object Pascal, Perl, PHP, Python, R, Ruby, Scala, Simula, Pharo, Smalltalk ja Swift.
Käsitteitä Olio () on ohjelmiston rakenteellinen perusyksikkö. Se ei ole puhtaasti toiminnallinen tai puhtaasti tietoa säilyttävä, vaan se sisältää kummankin aspektin.Koskimies, s. 30.
Olio-ohjelmointi jakautuu kahteen pääsuuntaukseen. Smalltalkin sanastossa oliot kommunikoivat keskenään lähettämällä ja vastaanottamalla viestejä. Viestin vastaanottaminen suorittaa määritellyn toiminnon vastaanottavassa oliossa. Simulan tai C++:n sanastossa oliot kutsuvat toisensa jäsenfunktioita.
Oliota käytetään ohjelmistosuunnittelussa esittämään jonkun abstraktin tai reaalimaailman käsitteen ilmentymää ohjelmistossa. Oliokielillä laaditut ohjelmat koostuvat tavallisesti lukuisista olioista, joiden yhteistoiminnan tuloksena on ratkaisu ohjelmointiongelmaan. (kts. myös oliomalli)
Olio pystyy pyydettäessä tekemään sille ominaiset toiminnot, joita kutsutaan metodeiksi tai jäsenfunktioiksi kielestä riippuen. Metodi koostuu nimestä, mahdollisista parametreista ja toiminnan määrittelevästä rungosta. Olio tallettaa tietoja attribuutteihin.
Luokka (class) on määritelmä, joka kuvaa samanlaisten olioiden yhteisen rakenteen ja yhteisen käytöksen. Toisin sanoin luokka on ohje olion luomiselle ja sitä voidaan pitää olion tyyppinä. Olio on siten luokan ilmentymä, instanssi.Koskimies, s. 37. Esimerkiksi henkilörekisteriohjelmassa määritellään 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ä. 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. On olemassa myös vähemmän tunnettuja prototyyppipohjaisia kieliä, jotka eivät tunne luokkakäsitettä.
Sidonta (binding) tarkoittaa sitä, miten symbolinen nimi yhdistetään dataan tai koodiin. Kaksi tapaa ovat myöhäinen ja varhainen sidonta. Joko kääntäjä tekee sen käännöksen yhteydessä, jolloin puhutaan staattisesta (varhainen) sidonnasta, tai se tapahtuu ajonaikana, jolloin kyseessä on dynaaminen (myöhäinen) sidonta. Jossain tilanteissa objektin tyyppi ei ole tiedossa vielä käännösaikana, jolloin on käytettävä dynaamista eli myöhäistä sidontaa.
Perintä (inheritance) mahdollistaa uusien luokkamääritysten tekemisen vanhojen määritysten pohjalta. Periyttämisen ansiosta on mahdollista käyttää uudestaan jo tehtyä ohjelmakoodia uusien luokkien pohjana. Periyttäminen mahdollistaa myös abstraktien perus-/kantaluokkien, joista periytetään useita luokkia, joita kaikkia voidaan käyttää samannimisillä funktioilla ja samoilla parametreilla kuin abstraktia kantaluokkaa, käytön. Itse abstraktista kantaluokasta ei voi luoda omia instansseja eli olioita new-operaattoria käyttäen. Oliot on luotava tässä tapauksessa abstraktin luokan lapsiluokista. Esimerkkinä abstrakti luokka voisi olla ajoneuvot-luokka, jolla olisi vuosimalli jäsenmuuttujana ja funktiona/metodina "rekisteröi"-toiminto. Lapsiluokkia voisivat olla esimerkiksi auto- ja laiva-lapsiluokat, jotka perivät ajoneuvoluokan jäsenmuuttujat ja funktiot. Perinnässä tärkeä huomionarvo on myös kantaluokan näkyvyysmääreiden asettaminen. Tämä johtunee siitä, että kantaluokan "private"-nimikkeellä määritetyt jäsenmuuttujat ja funktiot eivät periydy alempiin luokkiin. Näkyvyysmääreeksi on asetettava vähintään "protected", jotta lapsiluokka perii kyseisen jäsenmuuttujan tai funktion onnistuneesti. Periyttäminen ja abstraktien perusluokkien käyttö ovat oliopohjaisten kielien vahvimpia mutta myös vaikeimpia ominaisuuksia. Periyttäminen mahdollistaa abstraktit rajapinnat, joiden kautta voidaan käsitellä tuntemattomien tahojen rakentamia olioita ennalta määritellyllä tavalla.
Moniperintä (multiple inheritance), mahdollistaa uuteen luokkaan periyttämisen useista kantaluokista. Moniperintä on hyödyllistä tilanteessa, jossa "lepakko" sisältää "lentävä eläin"- ja "nisäkäs"-luokkien ominaisuudet. Moniperintä on tuettu kielissä kuten C++, Eiffel, OCaml ja Scala. C++ tukee virtuaalista moniperintää, jonka avulla periytyy vain yksi toteutus yhteisen kantaluokan jäsenistä. Kaikissa oliokielissä moniperintä ei ole mahdollista. Eräissä kielissä moniperintä on vain rajatusti mahdollista. Rajattua moniperintää (interface eli rajapintaperintää) tukevat kielet kuten Ada, C# ja Java. JavaScript käyttää perimisen toteuttamiseen prototyyppejä.http://www.crockford.com/javascript/inheritance.html
Kapselointi (encapsulation) -termiä käytetään kahdessa merkityksessä. Ensimmäisen merkityksen mukaan kapseloinnin ideana on datan ja käyttäytymisen kokoaminen yhteen yksikköön, olioon. Toinen merkitys lisää tähän vielä tiedonpiilotuksen: olion sisäisiin muuttujiin ei (pääsääntöisesti) päästä suoraan käsiksi olion ulkopuolelta, jolloin ohjelmointivirheiden määrä vähenee. Olion käyttäjän ei tarvitse tietää enää käyttövaiheessa sitä, miten olio toimii sisäisesti: riittää, kun tietää, miten oliota itseään käytetään ja miten olio käyttäytyy. Olion käyttäjät voivat käyttää oliota sen julkisen rajapinnan kautta (public interface). Olion luokkakuvauksessa voi olla myös yksityisiä muuttujia tai funktiota (private interface), jotka ovat vain olion itsensä käytettävissä.
Konstruktorihttps://tieteentermipankki.fi/wiki/Nimitys:konstruktori (constructor, rakentaja) on metodi, joka alustaa luokan ilmentymät.https://www.cs.helsinki.fi/u/laine/oliosanasto/ RAII-konseptissa konstruktori myös varaa resurssit, jotka vapautetaan destruktorissa.
Destruktori (destructor, hajottaja tai purkaja) on metodi, joka vapauttaa olion varaamat resurssit.
Polymorfismi eli monimuotoisuus tarkoittaa sitä, että yhtä rajapintaa käytetään eri tyyppien käsittelyyn, tai yksi symboli edustaa monia tyyppejä. Esimerkiksi funktio tai datatyyppi voidaan kirjoittaa siten, että se voi käsitellä dataa riippumatta sen tyypistä.
Virtuaalimetodi on ominaisuus, jolla perintää käyttävä olio voi korvata yliluokassa olevan metodin toteutuksen toisella.
Luokkafunktiot esittävät luokan palveluja sekä operaatioita, jotka eivät kohdistu yksittäiseen olioon. Jos jäsenfunktiot ovat samankaltaiset määrittelyn kanssa lisätään static-avainsana, ei voida käyttää olemassa olevan olion jäsenmuuttujia eikä this-avainsanaa ja voi käyttää luokkamuuttujia. Luokalla voi olla useampi luokkafunktio, eikä luokkamuuttujan tarvitse aina olla julkinen.
Abstrakti luokka (Abstract class) on yksi olio-ohjelmoinnin peruskäsitteistä, joka mahdollistaa yleisten ominaisuuksien ja toimintojen jakamisen eri luokkien välillä. Abstrakti luokka ei pysty luomaan olioita, mutta se voi sisältää yhden tai useamman abstraktin metodin. Abstrakti metodi on määritelty luokassa, mutta sille ei ole toteutusta. Abstrakti luokka toimii pohjana lapsiluokille, joissa ne pitää toteuttaa.
Singleton (ainokainen) on suunnittelumalli, joka varmistaa että tietyn luokan oliolla on vain yksi instanssi ja että kaikkilla osilla on pääsy tähän samaan instanssiin. Singleton toteutetaan yleensä staattisella metodilla, joka palauttaa saman instanssin jokaiselle kutsujalle. Singleton on hyödyllinen erityisesti silloin, jos halutaan varmistaa että luokalla on vain yksi käyttötapaus.
Perintö (inheritance) on keskeinen olio-ohjelmoinnin käsite, joka tarkoittaa sitä, että uusi luokka voi periä vanhemman luokan toimintoja tai ominaisuuksia. Perintö auttaa koodin järjestelyssä ja ylläpitämisessä ja mahdollistaa sen uudelleenkäytön, jos niin halutaan.
Rajapinta (interface) on määritelmä siitä, miten luokka kommunikoi ja toimii muiden luokkien kanssa. Rajapinta määrittelee, mitä toimintoja ja ominaisuuksia luokka tarjoaa muille luokille. Rajapinta mahdollistaa erilaisten luokkien yhteensopivuuden ja helpottaa koodin ylläpitoa. Rajapinta ei siis ole itse toteutus vaan kertoo pelkästään, mitä toimintoja luokalla on. Rajapinnan toiminnot täytyy määritellä erikseen niissä luokissa, jotka käyttävät tätä pintaa.
Esimerkki
Pseudokielinen esimerkki luokkakuvauksesta luokalle "Oppilas": // Aloitetaan kantaluokan määrittely class Henkilö { protected: String nimi; // yhteinen jäsenmuuttuja kaikille henkilöille
public: function asetaNimi( String nimi) { this.nimi = nimi;
// Periytetään luokka Opettaja kantaluokasta.