Olio-ohjelmointi
Periaatteita

Abstraktio tarkoittaa kokonaisuuksien käsittelyä, jossa tarkennetaan vain tarvittaessa. Kokonaisuuksien hahmotus katoaa, kun alamme lisäämään yksityiskohtia. Abstraktio on tällöin juuri yksityiskohtien piilottamista, jotta kokonaiskuvaa parannee. Tätä tiedon piilottamista kutsutaan olio-ohjelmoinnissa kapseloimiseksi.
Kapselointi on attribuuttien ja metodien sitomista yhteen luokassa. Kapseloinnin avulla luokan sisäiset yksityiskohdat voidaan piilottaa ulkopuolisilta. Luokalla on metodeja, jotka tarjoavat käyttöliittymiä, joiden avulla luokan tarjoamia palveluita voidaan käyttää. Kapselointi estää ulkoista koodia käsittelemästä olion sisäistä toimintaa, eli olio tarjoaa palvelut ainoastaan rajapintansa kautta, jolloin olion luokan sisäisellä toiminnalla ei ole merkitystä, kunhan metodikutsut toimivat samalla tavalla. Tämä mahdollistaa luokan sisäisen koodin uudelleenkirjoituksen, jos rajapinta (parametrit, paluuarvot ja metodikutsut) pidetään samana. Kapselointi motivoi ohjelmoijat sijoittamaan samaan kokonaisuuteen liittyvän datan yhteen luokkaan, mikä lisää koodin ymmärrettävyyttä ja ylläpidettävyyttä. Koska selkeärajaisten luokkien kapselointi vähentää luokkien välistä datan siirtoa, minimoi se samalla koheesiota.
Olioiden kapselointia voidaan edistää näkyvyysmääreillä, jotka piilottavat olioiden dataa, jolloin olion jäsenmuuttujiin ei pääse ulkopuolelta käsiksi, mikä vähentää niiden väärinkäyttöä. Tällaista abstraktiota syntyy, jos luokka ei salli pääsyä sen sisäisiin tietoihin ilman, että jotain luokan metodia kutsutaan. Jotkin kielet (esimerkiksi Java) mahdollistavat luokkien pääsyrajoitusten eli näkyvyysmääreiden muokkaamisen, jolloin luokan sisäisiä tietoja voidaan merkitä private avainsanalla, ja luokan ulkopuoliseen käyttöön tarkoitetut metodit voidaan merkitä avainsanalla public. Myös näiden kahden vaihtoehdon välillä on avainsana protected, joka mahdollistaa metodin tai jäsenmuuttujan periytymisen luokan alaluokkiin, pitäen ne kuitenkin muiden luokkien olioilta piilossa. Muissa kielissä (kuten Pythonissa) abstraktiota helpottavien näkyvyysmääreiden suoraa vastinetta ei ole, vaan ohjelmoija toimii yleisesti hyväksyttyjen tapojen mukaan (esimerkiksi yksityisillä metodeilla voi olla alaviivalla alkavia nimiä).
Abstraktiot voidaan luokitella: "is-a" ja "has-a" -abstraktioihin. Asiaa pilkkoessamme käytämme "has-a"-abstraktiota, kun pohdimme, mistä kokonaisuus koostuu esim: Pullo koostuu itse pullosta, etiketistä, korkista ja sisällöstä. Erikoistuminen taas kuvaa "is-a" -abstraktiota. Tällöin mietimme, mitkä luokat kuuluvat laajempiin luokkiin. Tämä muodostaa perustan luokkien väliselle periytymielle esim: lasipullo on pullo, ja pullo on pakkaus.
Hierarkia olioiden tietojäsenten välillä on tärkeä osa olio-ohjelmointia. Toisin sanoen se on abstraktion järjestämistä tai järjestelyä. Hierarkia mahdollistaa systeemin kokoamisen pienemmistä yhdistetyistä kokonaisuuksista, jotka voivat koostua vielä pienemmistä kokonaisuuksista, kunnes pienin mahdollinen systeemin taso on saavutettu. Hierarkian perustuu "Hajota ja hallitse" -periaatteeseen, jossa ongelmaa pilkotaan pienempiin helposti ratkaistavampiin osiin, joista lopullinen ratkaisu kootaan.
Olio-ohjelmoinnissa pyritään olioiden hyvään koheesioon. Olioiden tulee vastata jotakin yksiselitteistä ja selkeärajaista käsitettä. Olion tietojäsenet liittyvät kiinteästi toisiinsa. Esimerkiksi opintorekisteritietojärjestelmässä ei samaan olioon tallenneta opiskelijan ja hänen käymiensä kurssien tietoja, vaan opiskelijaolio sisältää pelkästään opiskelijan tiedot ja viittaukset opintosuoritusolioihin.
Olioiden välisten riippuvuuksien hallinta on tärkeää laajoissa oliojärjestelmissä. Oliolla on riippuvuus kaikkiin niihin olioihin, joille se lähettää viestejä. Olioiden tulisi kommunikoida vain muutamien läheisesti olioon liittyvien olioiden kanssa. On vältettävä tilannetta, jossa järjestelmän kaikki oliot joutuvat olemaan tietoisia suuresta määrästä muita olioita eri puolilta järjestelmää.
Olioita pyritään ohjelmoimaan niiden rajapintoja vastaan. Rajapinta kuvaa olion tarjoamat palvelut, eli mitä olio tekee. Olion toteutuksen yksityiskohdat, eli miten olio toimii, pyritään piilottamaan muilta olioilta. Käytännössä olion rajapinta koostuu sen julkisista metodeista ja jäsenmuuttujista. Oliolla voi olla myös suojattuja metodeja ja jäsenmuuttujia, jotka eivät ole käytettävissä olion ulkopuolelta. Usein jäsenmuuttujien käsittely olion ulkopuolelta estetään ja olion tilaa voidaan käsitellä vain sen jäsenfunktioiden avulla.
Rajapintaluokat (interface) määrittelevät pelkästään rajapinnan ilman toteutusta. Rajapintaluokkien käyttö mahdollistaa tietyn toiminnon toteutuksen varioimisen ohjelmassa. Konkreettiset luokat, jotka perivät rajapintaluokan, voivat toteuttaa rajapintaluokan määrittelemän rajapinnan haluamallaan tavalla.
SOLID on yksi olio-ohjelmoinnin pääperiaatteista. Periaatteet esitteli ensin Robert J. Martin, mutta SOLID lyhennettä käytti ensin Michael Feathers.
SOLID koostuu seuraavista säännöistä:
Yhden vastuun periaate (Single Responsibility Principle): Luokalla tulisi olla vain yksi tehtävä, ja siksi vain yksi syy muuttua.
Avoin-suljettu periaate (Open-Closed Principle): Luokkien kuuluu olla avoimia laajennukselle ja suljettuja muokkaukselle.
Liskovin korvausperiaate (Liskov Substitution Principle): Liskovin periaatteen mukaan kantaluokan olio pitäisi aina pystyä korvaamaan alaluokan oliolla.
Rajapinnan erotteluperiaate (Interface Segregation Principle): Rajapinnat pitää olla eroteltu eri tarkoituksiin, yleisiä rajapintoja pitää välttää.
Riippuvuuden käänteisyyden periaate (Depency Inversion Priciple): Luokkien tulisi riippua rajapinnoista ja abstrakteista luokista, konkreettisten luokkien ja funktioiden sijaan.
Polymorfismi tarkoittaa olioiden kykyä ottaa monta muotoa. Sen nimi tulee kreikan “poly”, joka tarkoittaa lukuista ja “morphs” tarkoittaa muotoa. Esimerkiksi ihminen voi olla jonkun lapsi, puoliso ja työntekijä samaan aikaan ja käyttäytyä eri tavalla eri tilanteessa. Samalla tavalla kantaluokan lapsiluokat voivat määrittää oman käyttäytymisensä ja jakaa osan kantaluokan samoista toimintatavoista.
Polymorfismi tapahtuu, kun luokka perii ominaisuuksia toiselta luokalta. Yleisin tapaus on se, kun kantaluokan viittausta käytetään viittaamaan lapsiluokkaobjektiin. Voidaan selvittää, onko objekti polymorfinen, suorittamalla “is-a” tai “instanceof” testejä. Javassa kaikki oliot ovat polymorfisia.
Polymorfismin ominaisuudet ovat metodien toiminnallisuuden eri käyttäytyminen eri skenaarioissa, metodien käyttäytymisen riippuvuus eri annetuista tiedoista, jäsenien tai metodien sama nimi erityyppisissä luokassa, implisiittisen tyyppimuunnoksen tukeminen.
Javassa on kaksi tyyppiä polymorfismia. Staattisessa polymorfismissa luokassa on useita metodeja, joilla on sama nimi samassa luokassa, mutta jokaisella on eri määrä parametreja tai eri tietotyyppien parametreja. Sellaisia funktioita kutsutaan ylikuormituksiksi (method overloading). Metodikutsun käsittelee kääntäjä. Toinen polymorfismin tyyppi on dynaaminen. Se esiintyy, kun lapsiluokalla on oma määritelmänsä yhdelle kantaluokan jäsenmetodeista. Tätä kutsutaan metodin ohitukseksi (method overriding). Näiden kahden polymorfismin välillä ero on se, että staattinen polymorfismi kerää tiedot metodin kutsumiseksi käännöshetkellä, kun taas dynaaminen polymorfismi kerää tiedot metodin kutsua varten ajon aikana.
Polymorfismi eroaa periytymisestä. Periytymisessä ilman polymorfiaa lapsiluokka perii samat kantaluokan attribuutit ja metodit ilman muutoksia niiden toimivuuteen. Polymorfismissa lapsiluokka perii attribuutit ja metodit, mutta tarjoaa näille menetelmille oman toteutuksen.
Periytymisessä aliluokan vastuulla on jäsenmuuttujien ja muiden tietorakenteiden alustaminen ja kantaluokan vastuulla on pitää huoli, että aliluokan olion kantaluokkaosa alustetaan oikein. Aliluokka tarjoaa kaikki samat palvelut mitä kantaluokkakin ja mahdollisesti vielä jotain omaa. Aliluokan olio on tyypiltään myös kantaluokan olio.
Toinen käytetty olio-ohjelmoinnin periaatteista on Craig Larmanin kirjassaan Applying UML and Patterns kuvailema GRASP, eli General Responsibility Assignment Software Patterns. Se on kahdeksan periaatteen kuvailema suhde suunnittelun ja vastuunjakamisen välillä. GRASP periaatteet ovat ohjaaja, luoja, informaatioasiantuntija, alhainen yhteenliittäminen, korkea koheesio, polymorfismi, suojatut variaatiot ja täydellinen fabrikaatio. GRASP periaatteita voidaan käyttää SOLID periaatteiden tapaan hahmottamaan ja kuvailemaan yleisiä olio-ohjelmoinnin ongelmia sekä niiden ratkaisuja. Olio-ohjelmoinnin periaatteet eivät ole fyysisiä työkaluja, vaan ajatusmalleja, joiden avulla voidaan kehittää parempaa sekä selkeämpää koodia. Yhdessä kummatkin periaatteet määrittelevät keskeisiä olio-ohjelmoinnin konsepteja sekä kehitysmalleja.