812347A Olio-ohjelmointi,
2015 syksy 2. vsk
IV Periytyminen ja
monimuotoisuus
Sisältö
1.
2.
3.
4.
5.
6.
Periytyminen
Johdanto monimuotoisuuteen
Ylikuormittaminen
Uudelleenmäärittely
Muuttujien monimuotoisuus
Multimetodit ja double dispatch
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
2
IV.1 Periytyminen
Uudelleenkäytetään olemassaolevan luokan
ominaisuuksia määriteltäessä uutta luokkaa
Periytyvää luokkaa kutsutaan kantaluokaksi, perivää
luokkaa aliluokaksi
Periytymissuhteista muodostuu luokkahierarkia
C++ tukee moniperiytymistä
Perivä luokka perii useamman kantaluokan
C++:ssa kolmen tyyppistä periytymistä
Julkinen periytyminen
Suojattu periytyminen
Yksityinen periytyminen
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
3
IV.1.1 Julkinen periytyminen
Tulee käyttää, kun perivää tyyppiä voidaan käyttää aina
samassa yhteydessä kuin kantaluokkaa
IS-A, WORKS-LIKE-A - periytyminen
Tyyppiperiytyminen
Perii sekä liittymän että toteutustavan
Periytyminen näkyy luokkahierarkiasta ulospäin
Yleisin periytymisen muoto
Javassa ainoa
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
4
IV.1.1.1 Julkinen periytyminen ja näkyvyys
Kantaluokan yksityiset (private) jäsenet eivät näy
aliluokassa
Periytyvät kuitenkin
Ei voi siis käyttää suoraan
Kantaluokan suojatut (protected) ja julkiset (public)
jäsenet näkyvät aliluokassa
Voidaan siis käyttää suoraan
Jäsenten näkyvyys myös säilyy samana
periytymisessä
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
5
Esimerkki julkisesta periytymisestä
class A
{
public:
void f(int);
};
class B: public A // B perii luokan A
{
public:
void f(double);
};
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
6
Esimerkki julkisesta periytymisestä (2)
A a;
B b;
double x = 1.0;
a.f(x);
b.f(x);
// Kutsuu A::f(int)
// Kutsuu B::f(double)
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
7
Periytyminen graafisesti
ColoredPoint
Point
-double x_coord
-double y_coord
-int color
ColoredPoint perii
Point-luokan
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
ColoredPoint-olio
sisältää Pointluokan olion
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
8
IV.1.1.2 Periytyminen ja muodostimet
Kantaluokan jotakin muodostinta kutsutaan aina
ensimmäiseksi kun aliluokan muodostinta kutsutaan
Olio rakennetaan kantaluokasta aliluokkaa kohti
Ellei aliluokan muodostimessa eksplisiittisesti kutsuta
kantaluokan muodostinta, niin kutsutaan automaattisesti
kantaluokan oletusmuodostinta
Jos luokalla ei ole julkisia tai suojattuja muodostimia niin
sitä ei voida käyttää kantaluokkana
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
9
IV.1.1.2 Periytyminen ja hajotin
Kun aliluokan olio tuhotaan, aliluokan hajotinta
kutsutaan ensin ja sitten kantaluokan hajotinta
Olio tuhotaan aliluokasta kantaluokkaa kohti
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
10
Esimerkki muodostimista
class Kanta{
public:
Kanta() {...}
protected:
Kanta(int i) {...}
private:
};
class Ali : public Kanta{
public:
Ali();
Ali(int i);
);
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
11
Esimerkki muodostimista (2)
Ali::Ali() // implisiittinen Kanta() -kutsu
{
}
Ali::Ali(int i) : Kanta(i)
// eksplisiittinen Kanta(int) -kutsu
{
}
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
12
IV.1.2 Toteutustavan periytyminen
Joko yksityinen tai suojattu periytyminen
Yksityinen periytyminen
Kantaluokan (kantaluokkien) kaikki jäsenet ovat
yksityisiä alaluokassa.
public -> private
protected -> private
Kantaluokan yksityiset jäsenet eivät ole käytettävissä
Suojattu periytyminen
Kantaluokan (kantaluokkien) kaikki jäsenet ovat
yksityisiä alaluokassa.
public -> protected
protected -> private
Kantaluokan yksityiset jäsenet eivät ole käytettävissä
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
13
IV.1.3. Moniperiytyminen
Moniperiytymisessä luokka perii useamman kantaluokan
täsmälleen samoin kuin yksinkertaisessa perinnässä ->
aliluokalla on useampi kantaluokka
Johdettu luokka sisältää kantaluokan aliolion jokaisesta
sen kantaluokasta
Ensimmäisiä lisäominaisuuksia C++:aan
C++:ssa olioilla ei yhteistä kantaluokkaa -> moniperintä
katsottiin välttämättömäksi säiliöiden toteuttamiseksi
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
14
IV.1.3. Moniperiytyminen (2)
Kantaluokkien muodostimia kutsutaan siinä
järjestyksessä kuin ne on määritelty kantaluokiksi
Hajottimien kutsujärjestys on päinvastainen
B
A
C
A
B
C
B
A
C
B
A
Muodostin
C
Hajotin
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
15
IV.1.3. Moniperiytyminen: Esimerkki
class ZooAnimal{
public:
virtual ~ZooAnimal() {}
};
class Bear : public ZooAnimal{};
class Endangered {};
class Panda: public Bear, public Endangered{};
int main() {
Panda p; // Muodostimien kutsut:
// ZooAnimal, Bear, Endangered, Panda
}
// Hajottimien kutsut:
// ~Panda, ~Endangered, ~Bear, ~ZooAnimal
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
16
IV.1.3.1 Erotteleva ja yhdistävä moniperiytyminen
Oletusarvoisesti C++:ssa moniperiytyminen erottelevaa:
class
class
class
class
Kanta { // JNE
EkaSolmu: public Kanta { // JNE
TokaSolmu: public Kanta { // JNE
Ali: public EkaSolmu, public TokaSolmu { //JNE
Ali-luokka sisältää kaksi ilmentymää Kanta-luokan
tiedoista
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
17
IV.1.3.1 Erotteleva ja yhdistävä moniperiytyminen
(2)
Voidaan käyttää myös virtuaalista eli yhdistävää
moniperiytymistä:
class
class
class
class
Kanta { // JNE
EkaSolmu: public virtual Kanta { // JNE
TokaSolmu: public virtual Kanta { // JNE
Ali: public EkaSolmu, public TokaSolmu { //JNE
Nyt Ali-luokassa vain yksi ilmentymä Kanta-luokan
tiedoista
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
18
IV.1.3.2 Virtuaalinen moniperiytyminen graafisesti
A
B
C
A
A
B
C
D
D
Tavallinen,
erotteleva
moniperiytyminen
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
Virtuaalinen,
yhdistävä
moniperiytyminen
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
19
IV.1.3.3 Vertailua Javaan
Javassa ei moniperiytymistä
Javassa luokkien lisäksi rajapintoja (interface)
Rajapinnat sisältävät vain metodien esittelyjä, ei
toiminnallisuutta
Javan luokka voi periä yhden luokan mutta toteuttaa
(implements) sen lisäksi useita rajapintoja
Luokkaan toteutetaan rajapinnan esittelemät metodit
C++:ssa ei rajapinnan käsitettä
Voidaan toteuttaa tekemällä luokka, jossa vain
puhtaasti virtuaalisia metodeja
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
20
IV.2. Johdanto monimuotoisuuteen
Olio-ohjelmoinnin kolme tukipilaria:
1. Tiedon kapselointi ja kätkentä
2. Periytyminen
3. Monimuotoisuus
Monimuotoisuus (polymorfismi): Olion kyky reagoida
samaan viestiin eri lailla tilanteesta riippuen
Termillä ei yhtä yksikäsitteistä määritelmää
Ehkä tyypillisin olio-ohjelmointiparadigman
ominaisuus
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
21
IV.2.1 Monimuotoisuuden ilmenemismuodot
1. Operaation ylikuormittaminen
Tavallisimmin: Useampia samannimisiä funktioita
samassa moduulissa
2. Operaation uudelleenmäärittely
Sama metodi yli- ja aliluokissa
3. Muuttujien monimuotoisuus
Sama muuttuja voi viitata eri tyyppisiin olioihin
4. Geneerisyys
Tyyppiriippumattomuus, tyypit parametreina
Käsitellään myöhemmin
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
22
IV.3. Ylikuormittaminen (Overloading)
Metodin (funktion) nimi on monimuotoinen, ts.
samannimisellä metodilla useita toteutuksia
Poikkeavat parametrilistaltaan tai
Ovat eri näkymäalueessa
Kääntäjä päättelee kutsun parametrien perusteella,
mihin toteutuksen sidotaan
Staattinen monimuotoisuuden muoto
Toteuttamiseen ei tarvita oliokieltä
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
23
IV.3.1 Ylikuormittaminen näkymäalueen suhteen
Luokka muodostaa näkymäalueen -> eri luokissa voi olla
samannimisiä ja samantyyppisiä metodeja
Ei edellytetä semanttista yhteyttä metodien välillä
class DialogWindow {
public: void draw() {}
};
class Artist {
public: void draw(){}
};
Näkymäalueen suhteen
ylikuormitetut metodit
Tästä eteenpäin käsitellään ylikuormittamista parametrien
suhteen!
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
24
IV.3.2 Konstruktorin ylikuormittaminen
Erittäin yleistä, esim. Javan String-luokan konstruktoreita:
String()
... an empty character sequence.
String(char[] value)
... represents the sequence of characters currently
contained in the character array argument.
String(String original)
...Initializes a newly created String object so
that it represents the same sequence of characters
as the argument.
-> Voidaan luoda String-olioita mm. seuraavasti:
String s = new String(); // s = ””
char merkit[] = {’h’, ’e’, ’i’};
String t = new String(merkit); // t = ”hei”
String u = new String(t); // u = ”hei”
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
25
IV.3.3 Operaattoreiden ylikuormittaminen
Kielen operaattoreiden laajentaminen omille tyypeille
Parantaa ohjelman luettavuutta, mikäli operaattorin
semantiikkaa ei muuteta
Esimerkki: Kirjoitettu luokka Piste, joka mallintaa tason
pisteitä. Halutaan käyttää operaattoria + pisteiden
yhteenlaskuun:
Piste p(2,3);
Piste q(4,5);
Piste r = p+q; // r = (6,8);
Onnistuuko?
Javassa ei sallittu
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
26
IV.3.3 Operaattoreiden ylikuormittaminen (2)
C++:ssa operaattorit funktioita tai luokkien metodeja,
jotka voidaan ylikuormittaa
Lähes kaikki operaattorit ylikuormitettavia
Operaattoreiden ylikuormittamisella ei pystytä
muuttamaan
Operaattoreiden sidontajärjestystä
Tulkintasuuntaa
Uusia operaattoreita ei voi tehdä
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
27
IV.3.3.1 Esimerkki, operaattorit + ja +=
class Piste{
public: Piste& operator+=(const Piste &p);
// ...
};
Piste operator+(const Piste& p1,
const Piste& p2);
Piste& Piste::operator+=(const Piste &p){
x_coord = x_coord+p.x_coord;
y_coord = y_coord+p.y_coord;
return *this;
}
Piste operator+(const Piste& p1,
const Piste& p2){
Piste p(p1);
p += p2; return p;
}
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
Tiedosto
Piste.h
Tiedosto
Piste.cpp
28
IV.4 Uudelleenmäärittely (Overriding): Aluksi
Staattinen sidonta = aikainen sidonta
Metodin kutsu liitetään käännöksen aikana tiettyyn
aliohjelmaan
Dynaaminen sidonta = myöhäinen sidonta
Kutsuttava metodi päätellään vasta ohjelman
suorituksen aikana
Alityyppiperiaate (”Liskov substitution principle”):
Aliluokan olio voi esiintyä kaikissa yhteyksissä, joissa
yliluokan olio esiintyy
C++:ssa ei yleisesti voimassa
Javassa aina voimassa
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
29
IV.4 Uudelleenmäärittely
Aliluokan metodi saman niminen, sillä on sama
parametrilista ja paluuarvo kuin yliluokan metodilla
Yliluokan metodin toteutus “peittyy”
Javassa näkyvyysmääre ei saa olla aliluokassa
tiukempi, C++:ssa voi vaihtaa mielivaltaisesti
Dynaaminen sidonta + alityyppiperiaate tekevät
uudelleenmäärittelystä vahvan monimuotoisuuden
työkalun
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
30
IV.4.1 Virtuaalioperaatiot
Operaatio (metodi), johon voidaan soveltaa myöhäistä
sidontaa, on virtuaalioperaatio
Virtuaalioperaatio, jolle määritellään yliluokassa myös
toteutus, on kiinnitetty virtuaalioperaatio
Toteutus on oletus, voidaan syrjäyttää aliluokissa
Avoin virtuaalioperaatio = abstrakti metodi
Yliluokka ei määrittele toteutusta lainkaan
Luokka, jolla on abstrakteja metodeja, on abstrakti
luokka. Sellaisesta ei voida luoda olioita
Jos luokka ei ole abstrakti, se on konkreettinen
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
31
IV.4.1 Virtuaalioperaatiot: Haittoja
Metodien virtuaalisuus tekee ohjelmasta vaikeammin
ymmärrettävän ja heikentää luokkahierarkian
seurattavuutta
Virtuaalioperaatioiden ajonaikainen sitominen myös
hidastaa ohjelman suorittamista
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
32
IV.4.2 Virtuaalioperaatiot eri kielissä
Smalltalk ja Eiffel: Kaikki operaatiot virtuaalisia
Java: Operaatiot virtuaalisia, mutta ohjelmoija voi estää
korvaamisen aliluokissa (final)
C++ ja Simula: Ohjelmoija päättää, mitkä operaatiot
virtuaalisia
C++: oletus ei-virtuaalinen
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
33
IV.4.2.1 Esimerkki
class Person{
private:
string name;
public:
virtual void
print() const;
virtual void
tMeth(){};
Person(string
str):name(str){};
};
class Employee : public
Person {
private:
string status;
public:
void print() const;
Employee(string n, string
s):Person(n),status(s){};
};
Sidotaan dynaamisesti;
virtual pois -> sidotaan
staattisesti
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
34
IV.4.3 Dynaamisen sidonnan toteutuksesta
Miten löydetään kutsuttaessa oikea metodi?
Suoraviivaisin tapa: Tallennetaan jokaiseen olioon
ylimääräinen tietokenttä, joka osoittaa oikeaan metodiin
Haaskaa tilaa, ei yleensä käytetä
Useimmissa käännettävissä oliokielissä käytetään
virtuaalitauluja
Virtuaalitaulun alkiot ovat osoittimia metodeihin
Jos aliluokka ylimäärittelee virtuaalisen metodin,
osoitin tähän metodiin. Muussa tapauksessa yliluokan
metodiin
Saman luokan instansseilla yhteinen taulu
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
35
IV.4.3 Dynaamisen sidonnan toteutuksesta (2)
EE
Person-luokan
virtuaalitaulu
Person
Attributes
Methods
Virtual methods
print = &Person::print
tMeth = &Person::tMeth
p1
Employee
Person::print
Attributes
Person::tMeth
Methods
Virtual methods
print = &Employee::print
tMeth = &Person::tMeth
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
Employee-luokan
virtuaalitaulu
Person* p1 = new
Person();
Person* p2 = new
Employee();
Employee::print
p2
Person::tMeth
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
36
IV.4.4 Uudelleenmäärittelyn toteutuksesta
Korvaaminen (replacement)
Aliluokan metodi korvaa täysin yliluokan metodin
”Amerikkalainen semantiikka”
Tarkentaminen (refinement)
Aliluokan metodissa suoritetaan ensin yliluokan
metodi + muut määritellyt operaatiot
”Skandinaavinen semantiikka”
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
37
III.4.4 Toteutuksesta: Java ja C++
Korvaaminen yleisempi tapa nykykielissä
Tarkentamista käytetään konstruktoreissa
Sekä Java että C++: Aliluokan oliota luotaessa
kutsutaan aina jotakin yliluokan konstruktoria
Java ja C++: Konstruktoreita lukuunottamatta
käytetään korvaamista
Tarkentaminen voidaan määritellä tehtäväksi aliluokan
metodissa
C++: Yliluokka::metodi()
Java: super-viite
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
38
III.4.5 Kovarianssi (Covariant change)
Uudelleenmääritellyn metodin paluuarvo tai parametrit
muuttuvat samaan suuntaan luokkahierarkian kanssa
Ovat siis tarkempia kuin yliluokassa
Parametreissa kovarianssi ei yleensä onnistu
class Kanta {
public: virtual boolean equals(Kanta& k){/*Vrt.*/}
};
class Kovar: public Kanta {
public: boolean equals(Kovar& k) {
// EI KORVAA Kanta-luokan
// metodia equals(Kanta k)
return true; }
};
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
39
IV.4.5 Kovarianssi (2)
Paluuarvossa kovarianssi semanttisesti mahdollinen
Myös Javan uudemmissa versioissa onnistuu
class Yli {
};
// Yli-luokan alityyppi
class Ali: public Yli {
};
class KovarAli: public
Kovar {
public:
Ali* teeOlio() {
return new Ali();
}
};
class Kovar {
Paluuarvo muuttuu alaspäin
public:
virtual Yli* teeOlio(){ luokkahierarkiassa
return new Yli();
Korvaa Kovar-luokan
}
metodin teeOlio()
};
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
40
IV.4.6 Kontravarianssi (Contravariant change)
Uudelleenmääritellyn metodin paluuarvo tai parametrit
muuttuvat päinvastaiseen suuntaan luokkahierarkian
kanssa
Ovat siis yleisempiä kuin yliluokassa
Paluuarvossa hankala toteuttaa
Ei C++:ssa eikä Javassakaan käy
Parametreissa mahdollista ainakin kääntää
Eiffel-kielessä tapahtuu korvaaminen
C++:ssa ja Javassa ei tapahdu korvaamista
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
41
IV.4.6.1 Kontravarianssi paluuarvossa
Alla oleva C++-koodi ei käänny!
class Yli {
};
// Yli-luokan alityyppi
class Ali: public Yli {
};
class KontravarAli: public
Kontravar {
public:
Yli *teeOlio() {
return new Yli();
}
};
class Kontravar {
public:
Paluuarvo muuttuu ylöspäin
virtual Ali* teeOlio(){ luokkahierarkiassa
return new Ali();
}
};
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
42
IV.4.6.2 Kontravarianssi parametreissa
C++:ssa voi käyttää syntaktisesti, ei aiheuta metodin
uudelleenmäärittelyä
class Yli {
}
// Yli-luokan alityyppi
class Ali: public Yli {
}
class Kontravar {
public:
virtual void oper(Ali &a)
{
}
}
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
class KontravarAli extends
Kontravar {
public void oper(Yli &y) {
}
}
Parametri muuttuu ylöspäin
luokkahierarkiassa
Ei korvaa Kontravarluokan metodia oper()!
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
43
IV.5 Muuttujien monimuotoisuus
Muuttuja voi viitata monentyyppiseen olioon
Dynaamisesti tyypitetyissä kielissä kaikki muuttujat
monimuotoisia
Monet skriptikielet
Staattisesti tyypitetyissä kaikilla muuttujilla tyyppi, joka
annetaan määrittelyn yhteydessä
Esim. Java, C++
Muuttujan monimuotoisuus: Voi viitata myös
tyyppinsä alityyppisiin olioihin
Tyypillinen käyttötapa: monimuotoiset säiliöt
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
44
IV.5.1 Downcasting
Tyyppimuunnos, joka tapahtuu alaspäin
luokkahierarkiassa
Muunnos ylöspäin yleensä aina sallittu
Tarvitaan joskus, kun muuttuja yliluokan tyyppinen,
mutta halutaan kutsua aliluokan operaatiota, jota ei
yliluokassa ole
Varmistettava, että muunnos laillinen!
Yleensä kielessä mekanismi, jolla voidaan tarkistaa onko
sallittu
Java: instanceof-operaattori tarkistaa olion tyypin
C++: dynamic_cast-operaattori tarkistaa onko
muunnos laillinen
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
45
IV.6 Multi-metodit ja double dispatch
Ongelma: Ylikuormitettujen metodien parametrit voivat
olla alityyppejä ja ylikuormitetun metodin sitominen on
käännösaikaista. Miten metodikutsu saadaan toimimaan
tarkoitetulla tavalla, ts. kutsu tehtäisiin parametrien
ajonaikaisten tyyppien perusteella? (Multi-metodi)
Esim.
class Yli{
};
class Ali: public Yli
};
Metodeja:
void fun(Yli& x, Yli&
void fun(Yli& x, Ali&
void fun(Ali& x, Yli&
void fun(Ali& x, Ali&
{
Ohjelmassa:
Yli* a = ... Voivat viitata sekä YliYli* b = ... että Ali-luokan olioihin
y) // Mitä metodia kutsutaan?
y) fun(*a, *b);
y)
y)
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
46
IV.6.1 Multi-metodit ja double dispatch (2)
Edellinen ongelma hankala staattisesti tyypitetyissä
kielissä. Yksi ratkaisu: olio tietää itse oman tyyppinsä,
viesti ohjataan sen mukaan
Luokkiin kirjoitettava dynaamisesti sidottavat metodit,
jotka korvaavat toiminnan
class Yli{
void fun(Yli& x){
x.funYli(*this);}
void funYli(Yli& x){
//fun(Yli&,Yli&);}
void funAli(Yli& x){
// fun(Ali&,Yli&);}
};
class Ali: public Yli {
void fun(Yli& x){
x.funAli(*this);}
void funYli(Yli& x){
// fun(Yli&,Ali&)}
void funAli(Yli& x){
// fun(Ali&,Ali&)}
};
Pääohjelmassa:
Yli *a = new Ali();
Yli *b = new Ali();
a->fun(*b);
Ari Vesanen, Tietojenkäsitttelytieteiden laitos, Oulun yliopisto
812347A Olio-ohjelmointi, Periytyminen ja
monimuotoisuus
47
© Copyright 2025