- TituCPP 7. luento 8.11.
- Materiaali
- Esimerkit
- Moniperintäesimerkit
- Kloonaus
- Mjono
- Wrappers
- Kalvot
- Täydennystä perintään
- abstraktit ja rajapintaluokat
- abstrakti luokka == luokka, joka sisältää vähintään yhden pure virtual -metodin
- rajapinta == täysin abstrakti luokka, sisältää vain julkisten metodien määrityksiä ilman toteutusta
- perintä voidaan (mutta ei välttämättä kannata) korvata koostamisella ja rajapinnoilla
- Esim. omaa säiliöluokkaa tehdessä sisäinen toteutus saatetaan koostaa jostain Javan säiliöluokasta - perintää käyttämällä rajapinnasta saattaisi tulla sotkuinen, koska perityssä luokassa näkyvät kaikki alkuperäisen säiliöluokan julkiset metodit
- c++:n private- ja protected-perintä on toteutuksen kannalta lähellä koostamista (ehdolla, että luokassa on vain yksi "koostettava": yliluokka)
- koostaminen vaatii perintää enemmän koodia, koska täytyy kirjoittaa koostetun luokan metodeja kutsuvia "delegointimetodeja" koostavaan luokkaan
- rajapintojen käyttäminen johtaa laajassa luokkahierarkiassa helposti malliin, jossa lähes kaikki luokat toteuttavat useita rajapintoja - tällöin ongelma muuttuu luokkien suunnittelusta rajapintojen suunnitteluksi
- moniperintä ja rajapinnat
- moniperinnästä ks. oo-moniste
- [ http://www.mit.jyu.fi/vesal/kurssit/winohj/html/cpp/m65.htm ]
- käyttökohteita
- rajapintojen yhdistäminen
- luokkien (toteutuksen) yhdistäminen
- koostaminen valmiista ominaisuuskokoelmista (mixin)
- Rajapinnoilla perintä on yksinkertaista, koska yliluokilla ei ole attribuutteja
- Jos yliluokilla on attribuutteja, mutta ei yhteistä kantaluokkaa (eikä samannimisiä metodeja), perintä on melko helppoa hahmottaa (erotteleva moniperintä)
- jos samannimisiä (moniselitteisiä) metodeja, aliluokassa on yksilöitävä ::-operaattorilla, mitä kutsutaan
- aliluokka on samalla myös jokaisen yliluokkansa instanssi ja sisältää yliluokkiensa attribuutit
- ks. ambiguityesimerkki
- Jos kantaluokilla on yhteinen yliluokka, vaaditaan lisämäärittelyjä
- ks. oo-moniste
- [ http://www.mit.jyu.fi/vesal/kurssit/winohj/html/cpp/m69.htm ]
- oletuksena aliluokkaan tulee useita kopioita yhteisen yliluokan attribuuteista (toistuva moniperiytyminen)
- tämä voi olla sovellusalueesta riippuen järkevää tai (yleensä) ei
- esim. oo-monisteen "ympyräneliö" sisältäisi koordinaatit erikseen sekä ympyrälle että neliölle!
- kopioituminen voidaan estää käyttämällä "virtuaalista" (yhdistävää) perintää - tällöin varmistetaan, että moniperittävä (yli)luokka sisällytetään vain yhden kerran
- yhteisen kantaluokan konstruktoria kutsuttava suoraan alaluokasta
- ks. diamond-esimerkki
- periytyminen vai kooste?
- HUOM! Mietittäessä, pitäisikö perintää käyttää, tulee muistaa ns. korvausperiaate: aliluokan olion tulee aina olla "korvattavissa" yliluokan oliolla
- kirjan esimerkki: peritäänkö vai koostetaanko henkilö luokista insinööri, viulisti ja isä?
- Sovelluskehykset
- useimmat (erityisest) graafiset ja/tai web-sovellukset toteutetaan usein sovelluskehyksiä käyttäen, jotka tarjoavat sovellusten usein tarjoamia palveluita valmiina
- perinteisiä sovelluskehyksiä vcl (delphi), mfc (microsoft foundation classes), ruby on rails
- laajemmin: komponenttiarkkitehtuurit: com, ejb, corba jne
- kopioinnista ja sijoituksista
- yleensä kopiomuodostin ja sijoitusoperaattori pitää aina määritellä uudelleen, jos luokassa on dynaamisesti varattuja attribuutteja
- muuten vaarana "jaetut" osoittimet - vaarallista, jos molemmat oliot yrittävät tuhota samaa muistialuetta moneen kertaan
- huom. jaetut osoittimet voivat olla tehokas toteutusratkaisu, jos niiden käyttö on suunniteltu osaksi luokan toimintaa (esim. viitelaskurit, reference counting)
- huom. kopiomuodostimen kutsuminen perittäessä
- helppo keino kiertää kopiointi/sijoitus: kopiomuodostin ja sijoitusoperaattori private-attribuuteiksi
- sijoitusoperaattorin toiminta
- 1. tarkista, onko sama
- 2. kutsu yliluokan sijoitusoperaattoria, jos on
- 3. vapauta olemassaolevan olion resurssit
- 4. kopioi sijoitettavan olion tiedot sijoittavaan
- sisältö lähellä destruktorin ja kopionmuodostimen toimintaa, mutta niitä ei pidä kutsua suoraan!
- viipaloituminen vaarana sekä kopioinnissa että sijoituksessa, jos käytetään konkreettisia (pino-)olioita
- viipaloituminen yksi syy (toinen mm. virtuaalifunktioiden käyttö), miksi vectoreissa ja muissa säiliöluokissa säilötään osoittimia tai viitteitä, ei konkreettisia olioita
- viipaloitumisen voi välttää kopioinnissa kloonauksella (clone)
- määritellään clone-metodi, joka vastaa olion kopioinnista "oikeassa" luokassaan
- clone-metodin toteutus käyttää kopionmuodostinta, mutta on määriteltävä jokaisessa luokassa erikseen
- vastuu kloonin muistinhallinnasta siirtyy kutsujalle.
- c++ vs java: javassa määritelty vakiona Cloneable-rajapinta, jonka toteuttavat luokat ovat kloonattavissa (muuten käytetään viitekopiointia)
- Operaattorien kuormitus
- kertaus: c++:n tyypinmuunnosoperaattorit
- Moniste, luku 18
- [ http://www.mit.jyu.fi/vesal/kurssit/cpp/moniste/html/m-Operaatt.htm ]
- Wrappers-esimerkki
- mahdollistaa omien "algebrallisten rakenteiden" määrityksen
- esim. kompleksiluvuilla laskenta, matriisialgebra
- rajoituksia operaattorien argumenttien määrän suhteen
- esim. []-operaattori ottaa yhden argumentin, mutta ()-operaattorilla määrä voi vaihdella => matriisin alkioon viittaus kannattaa tehdä ()-operaattorilla
- <<- ja >>-operaattoreilla mikä tahansa olio tuotavissa tai vietävissä tietovirtaan
- operaattorien kuormituksessa kannattaa olla maltillinen - ohjelman tulee toimia, kuten käyttäjä odottaa (esim. uudelleenmääritellyn +-operaattorin ei tulisi toimia kertolaskun tapaan jo laskujärjestyksen takia)