Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

Periytyminen

Toinen oleellinen perustekniikka olio-ohjelmoinnissa koostumisen lisäksi on periytyminen. Periytymisellä tarkoitetaan, että luokka voi 'periä' toisen luokan kaikki ominaisuudet ja toiminnallisuudet (ja muokata niitä, sekä lisätä niihin omiaan). Tämä edistää koodin uudelleenkäyttöä, sillä tällä tekniikalla voimme hyödyntää jo olemassa olevaa koodia, mutta lisätä siihen tarvittavat uudet ominaisuudet tai muuttaa perittyjä osia.

Periyttämisestä käytetään myös nimeä erikoistaminen (specialization) ja vastaavasti yhteisten metodien ja muuttujien siirtämistä omaan luokkaansa kutsutaan yleistämiseksi (generalization). Perimimisjärjestyksessä aikaisempaa luokkaa kutsutaan vanhemmaksi (parent) ja siitä perivää luokkaa lapseksi (child). Image Added

Periytyminen C++:ssa esitetään seuraavasti:

Code Block

class Perillinen : [määre] Vanhempi
{
...
}

...

Wiki Markup

jossa \[määre\] on yleensä 

...

_public_ (joskus harvoin protected tai private).

...

Anchor
esim1
esim1

Esimerkki 1.

...

Periytyminen.

...

Seuraavassa

...

on

...

esitetty

...

ensin

...

luokka CElain:

elain.h:

Code Block


class CElain
{
private:   // saatavissa vain luokan funktioilla
       char m_Kutsumanimi\[100\];
    int    float m_Massa;

public:   // voidaan käyttää luokan ulkopuolelta
       void AsetaNimi(char Nimi\[\]);
       char\* KysyNimi(char Nimi\[\]);
        void AsetaMassa(intfloat Massa);
    int    float KysyMassa();
};

Seuraavaksi

...

on

...

erikoistettu

...

luokka,

...

joka

...

esittää

...

eläintä

...

kissa, siihen sisällytetään kaikki vain kissalle ominaiset piirteet.

kissa.h:

Code Block

#include "elain.h" siihen sisällytettään kaikki   vain kissalle ominaiset piirteet.

class CKissa :   public CElain
{
private:   // saatavissa vain luokan funktioilla
    

public:    // voidaan käyttää luokan ulkopuolelta
       void Kehraa();
};
Luokan CKissa edustaja perii protected ja 

Luokka CKissa perii kaikki CElain-luokan ominaisuudet ja toiminnallisuudet (=jäsenmuuttujat ja -funktiot). Mutta ainoastaan protected ja public-tyyppisiin päästään käsiksi CKissa-luokassa. Kts. näkyvyys.

Image Added
Kuva 1. Esimerkki 1 UML-kielen luokkakaaviona esitettynä.

Vanhemman funktioiden ylikirjoitus perillisessä

Perityn luokan funktoita voidaan ylikirjoittaa perillisessä. Kutsuttaessa funktoita perillisen olion kautta suoritetaan perillisessä ylikirjoitettu funktio.

Anchor
esim2
esim2

Esimerkki 2. Funktion ylikirjoitus perillisessä.

elain.h:

Code Block

#include <stdio.h>public-tyyppiset  CElain-luokan metodit ja jäsenmuuttujat. Kts. näkyvyys.

Huom\!   public-määre ennen perittävää luokkaa määrittelee perinnän näkyvyyden.  Perinnässä voidaan käyttää myös private ja protected \-määreitä, mutta  niiden käyttö on erittäin harvinaista.

Vanhemman funktioiden ylikirjoitus perillisessä

Perityn luokan funktoita voidaan ylikirjoittaa perillisessä.  Kutsuttaessa funktoita perillisen olion kautta suoritetaan perillisessä  ylikirjoitettu funktio.

Esimerkki 2. Funktion ylikirjoitus perillisessä.

\#include <iostream>

using namespace std;

class CElain
{
public:   // voidaan käyttää luokan ulkopuolelta
&nbsp;&nbsp;&nbsp;    void TulostaLuokanNimi()
    {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cout <<         printf("Luokan nimi on CElain.\n");
  << endl;
&nbsp;&nbsp;&nbsp; }
};

lehma.h:

Code Block
#include "elain.h"

class CLehma : public CElain
{
public:
&nbsp;&nbsp;&nbsp;    void TulostaLuokanNimi()
    {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cout <<         printf("Luokan nimi on CLehma.\n");
  << endl;
&nbsp;&nbsp;&nbsp; }
};

main.cpp:

Code Block

#include "elain.h"
#include "lehma.h"

int main()
{
&nbsp;&nbsp;&nbsp;    CLehma lehma;
&nbsp;&nbsp;&nbsp;    lehma.TulostaLuokanNimi();

&nbsp;&nbsp;&nbsp;    CElain elain;
&nbsp;&nbsp;&nbsp; elain.TulostaLuokanNimi();
}

Testatkaa mitä main():ssa tehdyt funktiokutsut tulostavat.

h2    elain.TulostaLuokanNimi();
}

Image Added
Kuva 2. Esimerkin 2 luokkakaavio.

Testatkaa mitä main():ssa tehdyt funktiokutsut tulostavat.

Olion jäsenfunktioiden käyttö perillisestä

Vanhemman luokan jäsenfunktioita voidaan kutsua normaalisti, jos niitä ei ole ylikijoitettu.
Jos ne on ylikijoitettu, oletuksena kutsutaan aina perillisen versiota. Mieti seuraavaa tilannetta:

Code Block

#include "elain.h"

class CLehma : public CElain
{
public:
    void TulostaLuokanNimi()
    {
        TulostaLuokanNimi();
        printf("Luokan nimi on CLehma.\n");
    }
};

Tämä on loputon rekursio, eli funktio kutsuu itseään loputtomasti, sillä siinä ei ole lopetusehtoa.
Jos taas tarkoituksena oli kutsua vanhemman (CElain) TulostaLuokanNimi()-funktiota täytyy se määritellä eksplisiittisesti:

Code Block

#include "elain.h"

class CLehma : public CElain
{
public:
    void TulostaLuokanNimi()
    {
        CElain::TulostaLuokanNimi();
        printf("Luokan nimi on CLehma.\n");
    }
};

Tämä koodi toimii halutulla tavalla, eli CLehma-luokasta luodun olion TulostaLuokanNimi()-funktio kutsuu ensin vanhempansa, eli CElain-luokan funktiota TulostaLuokanNimi(), jonka jälkeen se tulostaa ruudulle oman tekstinsä.