Oliohjelmointi on kehittynyt proseduraalisesta ohjelmoinnista, jota harjoitettiin esimerkiksi C-kielellä. Tämän jälkeen kehittyivät kielet kuten Java ja C++, jotka sisälsivät olion käsitteen. Olion lisääminen ohjelmointiin oli vastaus tarpeeseen tehdä koodin rakenne selkeämmäksi ja enemmän todellista maailmaa vastaavaksi. Tässä yhteydessä oliot tarkoittavat koodissa määriteltyjä entiteettejä, jotka vastaavat todellisen maailman objekteja tai käsitteitä.
Oliot luodaan luokkien avulla. Luokka on eräänlainen kaava tai malli, joka määrittelee, mitä ominaisuuksia ja toimintoja oliolla on. Esimerkiksi, luokka ”Auto” voi määritellä, että jokaisella autolla on bensatankin koko ja maksiminopeus. Kun luokasta luodaan olio, se perii nämä ominaisuudet. Luokassa voidaan myös määritellä oliolle metodit, eli toiminnot, kuten autojen käynnistäminen tai tankkaaminen. Esimerkiksi GTA:ssa jokainen pelissä vastaantuleva auto luodaan Auto-luokasta ja ne kaikki jakavat samat ominaisuudet ja toiminnallisuuden.
Olio-ohjelmointi on siis lähtökohtaisesti perintä-pohjaista, aivan kuten Windowsin kansio-rakenne (esim. ”Auto”-kansio, jonka sisällä on alakansioita ja tiedostoja). Voidaan ajatella, että oliot periytyvät luokista, mutta myös luokat voivat periytyä toisista luokista. Rakenne voi tuoda selkeyttä, mutta se tuo myös kankeutta. Mainittakoon, että komponenttiohjelmoinnissa puolestaan asioita liitetään toisiin asioihin, sen sijaan että niillä olisi jokin vanhempi, aivan kuten tagi-systeemissä asiat identifioidaan liitettyjen tagien perusteella (esim. ”Auto”, johon on liitetty bensatankki-tagi).
Tarkastellaan esimerkkiä WinUI-kehitysympäristöstä. Tässä ympäristössä on jo valmiina luokka nimeltä ”MainWindow”, joka on määritelty avainsanalla `class`. Tämä luokka ei itsessään ole ikkuna, vaan määrittelee, miten ikkuna toimii. Luokkaan voidaan lisätä muuttujia (jotka määrittelevät ikkunan ominaisuudet) ja metodeja (jotka määrittelevät ikkunan toiminnallisuuden). Kun ohjelma käynnistetään, ”MainWindow”-luokasta luodaan ikkuna, joka on olio. Vaikka luokasta voidaankin luoda monta ikkunaa, yleensä tarvitaan vain yksi ”MainWindow”.
Omat luokat
Oman luokan luominen onnistuu kun kirjoitetaan `public class`, annetaan luokalle nimi, esimerkiksi ”Auto” ja lisätään sulkujen sisään tarvittavat komponentit.
public class Auto { }
Luokassa voidaan määritellä muuttujia, kuten `public int tankinKoko` ja `public int huippunopeus`. Kaikki tästä luokasta luodut oliot perivät nämä muuttujat. Jotta oliot saavat alkuarvonsa, käytetään konstruktoria, joka on erityinen metodi ilman palautusarvoa.
Konstruktorin nimi on sama kuin luokan nimi ja se määrittää olion alkuarvot. Konstruktoria kutsutaan, kun luokasta luodaan olio.
public class Auto { public int tankinKoko; public int huippunopeus; public Auto() { tankinKoko = 0; huippunopeus = 0; } }
Esimerkiksi, jos haluamme luoda uuden auton WinUI:ssä, menemme luokkaan ja luomme uuden muuttujan tyypillä ”Auto”, esimerkiksi nimeltään ”auto1”. Tämän jälkeen määritämme, että tähän muuttujaan sijoitetaan uusi olio käyttäen `new`-avainsanaa ja konstruktoria. Näin ollen, kun nappia painetaan, luodaan uusi ”Auto”-olio.
public MainWindow() { this.InitializeComponent(); auto1 = new Auto(); }
Tämän olion tankin koko ja huippunopeus voidaan asettaa toivottuihin arvoihin muuttamalla konstruktoria. Voimme siis asettaa konstruktorimetodille parametrin molempia jäsenmuuttujia varten ja sitten lähettää arvot argumentteina, kun uusi olio luodaan. Sitten konstruktorissa asetetaan vastaanotetut arvot jäsenmuuttujiin.
public class Auto { public int tankinKoko; public int huippunopeus; public Auto(int koko, int nopeus) { tankinKoko = koko; huippunopeus = nopeus; } } public sealed partial class MainWindow : Window { public Auto bmw; public Auto saab; public MainWindow() { this.InitializeComponent(); bmw = new Auto(100, 150); saab = new Auto(200, 250); } }
Nyt MainWindow-luokassa luodaan kaksi Auto-oliota (bmw ja saab), joille asetetaan eri tankin koot ja huippunopeudet. Tällä tavoin oliot ja luokat tarjoavat järjestelmällisen tavan hallita ja organisoida koodia ohjelmoinnissa. Ne mahdollistavat koodin jakamisen loogisiin osiin ja tekevät koodista helpommin ymmärrettävää ja ylläpidettävää. Olion jäsenmuuttujien tekeminen julkisiksi ei kuitenkaan ole paras mahdollinen vaihtoehto
Oletetaan, että haluamme luoda metodin, joka täyttää auton tankin. Tätä varten voimme luoda metodin, kuten `täytäTankki`, joka asettaa muuttujaan `bensanMäärä` arvon, joka vastaa tankin kokoa. Tämä tarkoittaa, että kun kutsutaan tätä metodia, se asettaa bensan määrän tankin maksimikapasiteetin mukaiseksi. Esimerkiksi, jos Saabin tankin koko on 200, kun metodia kutsutaan, bensan määrä asetetaan 200:aan.
public class Auto { //... public int bensanMaara; public Auto(int koko, int nopeus) { //... bensanMaara = 0; } public void taytaTankki() { bensanMaara = tankinKoko; } }
Lisäksi voidaan toteuttaa toinen metodi, `aja`, joka vähentää bensan määrää sen mukaan, kuinka paljon autoa käytetään. Esimerkiksi, joka kerta kun metodia kutsutaan, voidaan vähentää 20 yksikköä bensasta. Tämä tuo dynaamisuutta ohjelmaan, sillä se simuloi bensan kulutusta ajon aikana.
public void aja() { bensanMaara -= 20; }
Tämän jälkeen siirrytään olioiden hallintaan pääikkunassa (`MainWindow`). Kun `MainWindow` luodaan, luodaan samalla kaksi uutta auto-oliota. Nappia painamalla voimme kutsua Saab-olion `aja`-metodia, mikä aloittaa bensan määrän vähentämisen. Jos haluamme näyttää jäljellä olevan bensan määrän, voimme päivittää tekstikentän näyttämään Saab-olion bensan määrän. Koska bensan määrä on kokonaislukutyyppinen (int), meidän on muutettava se merkkijonoksi (String) ennen sen näyttämistä tekstikentässä.
Tämän jälkeen tulee esille tarve aloittaa ohjelma tietyllä bensan määrällä. Tämä voidaan tehdä kutsuttaessa konstruktoria. Esimerkiksi, jos Saab-olion tankki täytetään konstruktorissa maksimikapasiteettiin, kun `aja`-metodia kutsutaan ensimmäisen kerran, aloitetaan maksimimäärästä, ei nollasta.
public sealed partial class MainWindow : Window { public Auto bmw; public Auto saab; public MainWindow() { this.InitializeComponent(); bmw = new Auto(100, 150); saab = new Auto(200, 250); saab.taytaTankki(); } private void myButton_Click(object sender, RoutedEventArgs e) { saab.aja(); tekstikentta.Text = saab.bensanMaara.ToString(); } }
Visual Studiossa voit myös luoda uuden tiedoston luokalle painamalla projektia kakkospainikkeella Solution Explorerissa ja valitsemalla ”Add > Class…”
Anna sitten luokalle haluamasi nimi (Auto) ja valitse ”Add”. Nyt voit siirtää Auto-luokan koodin luomaasi tiedostoon, jolloin MainWindow-tiedoston sisältö pysyy selkeämpänä, kun siellä on vain ikkunaan liittyvä koodi.
♞
Edellinen osa: Metodit ja funktiot.