Wiki Markup |
---|
h1. Abstraktit luokat |
...
Yksi olio-ohjelmoinnin perusajatuksista on abstrahointi (abstraction), eli asioiden käsitteleminen abstraktilla tasolla |
...
Esimerkki 1. Abstrakti luokka.
Code Block |
---|
. !abstractKantaĺuokka.png|border=1! h3. Esimerkki 1. Abstrakti luokka. {code} class CElain { public: virtual ~CElain() {} // Toteutus tulee olla (tyhjäkin käy). virtual void Aantele() = 0; // Aito virtuaalifunktio. }; {code} Yllä esitellään luokka CElain, jossa on yksi aito virtuaalifunktio, _Aantele()_. Tämä tarkoittaa, että CElain luokasta ei voida luoda oliota. _Aantele()_\-metodin toteutus tulee olla toteutettuna perivässä luokassa. h3. |
...
Esimerkki 2. Abstraktin luokan toteuttava luokka. |
...
{code |
} class CKissa : public CElain { public: void Aantele() { printf("Miau!\n"); } }; {code} Tässä peritään CElain-luokka ja toteutetaan sen aito virtuaalifunktio _Aantele()_. h2. |
...
Abstraktien luokkien käsittely |
...
Abstrakteista luokista ei voida luoda olioita, ainoastaan niiden *ei-abstrakteista* perillisistä, joita myös kutsutaan (abstraktin luokan) toteuttaviksi luokiksi. Abstraktit luokat toimivat rajapintana (interface) toteuttavalle luokalle. Kts [polymorfismi]. h3. |
...
Esimerkki 3. Olioiden käsittely abstraktin (kanta)luokan avulla. |
...
CElain: |
...
{code |
} // Abstrakti luokka, eli kantaluokka. class CElain { public: virtual ~CElain() {} // Toteutus tulee olla (tyhjäkin käy). virtual void Syo() = 0; // Aito virtuaalifunktio. }; {code} CKissa: |
...
{code |
} // CElain-kantaluokan toteuttava luokka. class CKissa : public CElain { public: void Syo() { printf("Kissa syo kalaa...\n"); } }; {code} CKoira: |
...
{code |
} // CElain-kantaluokan toteuttava luokka. class CKoira : public CElain { public: void Syo() { printf("Koira syo lihaa...\n"); } }; {code} CElaintarha: |
...
{code |
} // Luokka johon voidaan tuoda CElain-luokan perillisiä. class CElainTarha { protected: CElain* Elaimet[100]; // 100 CElain-tyyppistä osoitinta taulukossa int ElainLaskuri; // laskuri, joka kertoo monta Elainta on lisätty ylläolevaan taulukkoon. public: CElainTarha() : ElainLaskuri(0) // nollataan ElainLaskuri { } ~CElainTarha() { // Vapautetaan Elaimet-taulukon olioiden varaama muisti: for (int i=0; i<ElainLaskuri; i++) { delete Elaimet[i]; } } bool LisaaElain(CElain* elain) { if (ElainLaskuri < 100) { Elaimet[ElainLaskuri] = elain; // Lisätään parametrina saatu elain-olio Elaimet-taulukkoon ElainLaskuri++; return true; } else { return false; } } void SyotaElaimet() { for (int i=0; i<ElainLaskuri; i++) { Elaimet[i]->Syo(); // Kutsutaan kaikkien Elaimien Syo()-funktiota. Huom! '->' käytettään '.' sijaan silloin kun käsitellään osoittimia... } } }; {code} {code |
} int main() { CElainTarha ElainTarha; ElainTarha.LisaaElain(new CKissa); ElainTarha.LisaaElain(new CKoira); ElainTarha.LisaaElain(new CKissa); ElainTarha.LisaaElain(new CKoira); ElainTarha.LisaaElain(new CKissa); ElainTarha.SyotaElaimet(); } {code} Esimerkki tulostaa seuraavat rivit: |
...
{noformat |
} Kissa syo kalaa... Koira syo lihaa... Kissa syo kalaa... Koira syo lihaa... Kissa syo kalaa... {noformat} Esimerkissä luodaan kantaluokka, CElain ja siitä periytetään kaksi perillistä, CKissa ja CKoira. Lisäksi luodaan CElainTarha-luokka, johon voidaan tuoda CElain-tyyppisiä osoittimia olioihin, riippumatta siitä, onko ne luotu CKissa vai CKoira \-luokista. Tämä onnistuu siksi, että molemmilla luokilla on sama kantaluokka, CElain. Kutsumme lopuksi CElainTarhan metodia SyotaElaimet(), joka 'syöttää' jokaista eläintä, eli kutsuu sekä kissojen että koirien Syo()-metodeita. |
...
Etuna tässä toteutustavassa on, että jatkossa voidaan luoda uusi CElain-luokan perillinen, esim. CKirahvi. Tästä luokasta tehty olio voidaan viedä CElainTarha-luokkaan, ilman että sen koodia tarvitsee muuttaa ollenkaan. |