812347A Olio-ohjelmointi, 2015 syksy 2. vsk - Oulu
Transcription
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