Virtuaalimetodi

Virtuaalimetodi tai virtuaalifunktio (, ) on olio-ohjelmointikielien ominaisuus, jolla perintää käyttävä olio voi korvata yliluokassa olevan metodin toteutuksen toisella. Virtuaalimetodeja tukevia kieliä ovat esimerkiksi C++ ja Object Pascal.

Virtuaaliosoitin () on funktio-osoittimen tapaus, jolla virtuaalimetodeihin viitataan.
Virtuaaliosoittimet sijoitetaan ajonaikaisesti virtuaalimetoditaulukkoon (, ).

Mikäli perityssä luokassa ei ole toteutusta virtuaalimetodille kutsut tehdään kantaluokan toteutukseen.
Abstrakti pure virtual metodi, jolla ei ole toteutusta kantaluokassa on pakko toteuttaa perityssä luokassa.

Tarkoitus 
Olio-ohjelmoinnissa, kun johdettu luokka perii kantaluokan, johdetun luokan olio voi olla viitattavissa kantaluokan tyyppisellä osoittimella tai viitteellä sen sijaan, että käytettäisiin johdetun luokan tyyppiä. Jos johdetussa luokassa korvataan kantaluokan metodeja, metodin, jota kutsutaan tällaisella viitteellä tai osoittimella, voi olla sidottu (linkitetty) joko 'varhaisessa' vaiheessa (kääntäjän toimesta) viitteen tai osoittimen deklaroidun tyypin mukaisesti tai 'myöhäisessä' vaiheessa (eli kielen suoritusjärjestelmän toimesta) viitteenä olevan olion todellisen tyypin mukaisesti.

Virtuaalifunktiot ovat määritelty 'myöhäisessä' vaiheessa. Jos kyseessä oleva funktio on 'virtuaalinen' kantaluokassa, kyseisen funktion toteutus kutsumiseen käytetään eniten johdettuun luokkaan kuuluvaa toteutusta, joka vastaa viitteenä olevan olion todellista tyyppiä, riippumatta viitteen tai osoittimen deklaroidusta tyypistä. Jos kyseessä ei ole 'virtuaalinen' funktio, menetelmä ratkaistaan 'varhaisessa' vaiheessa ja valitaan viitteen tai osoittimen deklaroidun tyypin mukaan.

C++:ssa virtuaalifunktiot määritellään lisäämällä virtual-avainsana funktion määrittelyyn kantaluokassa. Tämä muunnos periytyy kaikille johdettujen luokkien toteutuksille, joten ne voivat jatkaa toistensa korvaamista ja olla myöhäisesti sidottuja. Vaikka kantaluokan omistamat metodit kutsuisivat virtuaalista metodia, ne kutsuvat sen sijaan johdetun luokan metodia.

Kuormitus () tapahtuu, kun kahdella tai useammalla metodilla yhdessä luokassa on sama nimi, mutta erilaiset parametrit. Ylikirjoitus tarkoittaa kahta metodia, joilla on sama nimi ja parametrit. Kuormitus tunnetaan myös nimellä funktiovastaavuus ja ylikirjoitus dynaamisena funktio-kartoituksena.class Geometria
{
    virtual float pinta_ala() = 0; // pure virtual
    virtual int verteksilukum() { return 0; } // oletustoteutus
};

class Kolmio : public Geometria
{
    virtual float pinta_ala(); // määrittely
};

float Kolmio::pinta_ala() // toteutus
{
     return 42.0;
}

// kutsut virtuaalikutsujen kautta
Geometria *p = new Kolmio(); // käytetään kantaluokan osoitinta, ei tarvitse tietää varsinaista tyyppiä
float a = p->pinta_ala(); // perityn luokan toteutus
int l = p->verteksilukum();  // kantaluokan toteutus

Abstraktit luokat ja puhtaat virtuaalifunktiot 
Puhdas virtuaalifunktio tai puhdas virtuaalimetodi on virtuaalinen funktio, joka on toteutettava johdetun luokan toimesta, jos johdettu luokka ei ole abstrakti. Abstrakteiksi luokiksi kutsutaan luokkia, jotka sisältävät puhtaita virtuaalisia metodeja. Abstrakteja luokkia ei voi ilmentää suoraan. Toisaalta abstraktin luokan alaluokka voidaan ilmentää suoraan, jos kaikki perityt puhtaat virtuaaliset metodit on toteutettu emoluokan toimesta tai kyseisessä luokassa. Puhtailla virtuaalisilla metodeilla on melkein aina ilmoitus eli allekirjoitus eikä määritelmää eli toteutusta.

Vaikka puhdasta virtuaalista metodia yleensä ei toteuteta luokassa, joka määrittelee sen, puhdasta virtuaalista metodia voidaan joissain kielissä, kuten C++ ja Python, sallia sisältämään toteutus niiden julistavassa luokassa, tarjoten varakäyttäytymisen tai oletuskäyttäytymisen, johon johdettu luokka voi tarvittaessa delegoida.

Puhtaita virtuaalisia metodeja voidaan käyttää silloin, kun metodin määrittelyä käytetään rajapinnan määrittämiseen - samanlainen kuin Javan käyttöliittymän avainsana. Tällaisessa käytössä johdetut luokat tarjoavat kaikki toteutukset. Tässä suunnittelumallissa rajapintana toimiva abstrakti luokka sisältää vain puhtaita virtuaalisia toimintoja, mutta ei datajäseniä tai tavallisia metodeja. C++:ssa tällaisten puhtaasti abstraktien luokkien käyttö käyttöliittyminä toimii, koska C++ tukee moniperintää. Koska monet OOP-kielet eivät kuitenkaan tue moniperintää, ne tarjoavat usein erillisen liitäntä mekanismin. Esimerkkinä on Java-ohjelmointikieli.

Katso myös 
 Osoitin (ohjelmointi)

Lähteet

Viitteet

Olio-ohjelmointi