812347A Olio-ohjelmointi, 2015 syksy 2. vsk - Oulu

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