Esittely latautuu. Ole hyvä ja odota

Esittely latautuu. Ole hyvä ja odota

Olio-ohjelmointi: Luokkien kirjoittaminen

Samankaltaiset esitykset


Esitys aiheesta: "Olio-ohjelmointi: Luokkien kirjoittaminen"— Esityksen transkriptio:

1 Olio-ohjelmointi: Luokkien kirjoittaminen

2 Luokkien kirjoittaminen
Tähänmennessä on käytetty valmiiksi määritettyjä luokkia. Nyt opimme kirjoittamaan omia luokkia olioiden määrittämiseksi Seuraavaksi keskitymme näihin: Luokan määritykset Instanssin tieto (olion tieto) kapselointi ja tiedon muuttajat (setterit ja getterit) Metodin määrittäminen ja parametrien välitys Konstruktorit eli oletusmuodostimet (niiden korvaajat)

3 Missä ollaan? Luokan anatomia Kapselointi Metodin anatomia

4 Luokkien kirjoittaminen
Luokat, joita olemme aikaisemmin käyttäneet ovat Javan standardi luokkakirjastosta (API) Nyt alamme suunnitella ohjelmia, jotka perustuvat luokkiin joita itse kirjoitamme (kohdeluokat yms.) Luokka joka sisältää main metodin on vain ajettavan ohjelman käynnistyspiste Todellinen olio-ohjelmointi perustuu luokkien määrittämiseen (ei laiteta kaikkea mainin sisään, vain käynnistys!!!). Luokat esittävät olioita hyvin suunnitellun toiminnallisuuden ja attribuuttien kanssa

5 Luokat ja oliot Muista että oliolla on aina tila ja käyttäytyminen
Tarkastellaan kuusisivuista noppaa (yhtä noppaa) Sen tila voidaan määrittää siitä mitä sivua se näyttää ylöspäin Sen pääasiallinen käyttäytyminen on, että sitä voidaan heittää Voit ajatella samaa “realimaailmassa” esimerkiksi koskien coca-cola automaattia. Mikä on automaatin tila esim. Ja mikä on automaatin käyttäytyminen? Voimme esittää noppaa ohjelmistossa suunnittelemalla luokan Noppa tjoka mallintaa nopan tilan ja käyttäytymisen. Tuloksena saadaan noppa, joka on itseasiassa parempi kuin perinteinen noppa. Luokka toimii noppa olion piirustuksena Me voimme instantioida niin monta noppa-objektia kuin tarvitsemme missä tahansa ohjelmassa

6 Luokat Luokka voi sisältää tiedon määrityksiä ja metodimäärityksiä
int koko, paino; char kategoria; Tiedon määritykset Metodi määritykset

7 Luokat Tiedon arvot määräävät olion tilan, joka on luokasta luotu
Metodien toiminnallisuus määrittää olion käyttäytymisen Noppa luokkaamme voisimme määrittää int- tyyppisen muutujan, joka näyttää tällähetkellä ylöspäin osoittavan nopan sivun arvon Yksi metodeista “heittää” noppaa asettamalla tämän arvon satunnaislukuun, joka on ykkösen ja kuutosen välillä

8 Luokat Haluamme suunnitella Noppa luokkaan kaikki tarvittavat tiedot ja metodit, jotta se olisi monikäyttöinen ja uudelleenkäytettävä resurssi – Noppa.java, public class Noppa Mikä tahansa käyttävä ohjelma (Testeri) ei välttämättä käytä kaikkia ko. Luokan ominaisuuksia

9 Noppa luokka Noppa luokka sisältää kaksi arvoa
vakio MAX , joka esittää maksimaalista nopan arvoa muuttujan nopanArvo joka esittää nopan arvoa tällä hetkellä (ylöspäin oleva sivu heiton jälkeen) heitä metodi käyttää random metodia Math luokasta määrätäkseen nopan saaman arvon On myös olemassa metodeita, joilla eksplisiittisesti asetetaan ja noudetaan nopan arvo milloin tahansa

10 toString metodi Kaikkien luokkien, jotka esittävät olioita, pitäisi määrittää toString metodi toString metodi palauttaa merkkijono Stringin, joka esittää olion (tekstimuodossa, oliota ei luonnollisesti voi tulostaa suoraan) Sitä kutsutaan automaattisesti kun olio konkatenoidaan Stringiin (+ operaatio) tai kun olio välitetään println metodille

11 Konstruktorit eli oletusmuodostimet
Kuten aikaisemmin mainittu, konstruktori on erityinen metodi, jota käytetään olion alustamiseen, kun se alunperin luodaan Konstruktorilla on sama nimi kuin luokalla, ei palautusarvoa Noppa konstruktoria käytetään asettamaan jokaisen uuden noppa olion antamaksi lähtötulokseksi yksi Myöhemmin tutustutaan konstruktoreihin lisää

12 Tiedon näkyvyys (skooppi)
Tiedon näkyvyys on alue ohjelmasta, josta tiettyyn tietoon päästään viittaamaan (käyttämään sitä) Tietoon, joka määritetään luokkatasolla voidaan viitata luokan kaikista metodeista käsin Tietoon, joka määritellään metodin sisällä, päästään käsiksi vain ko. metodin sisällä Tietoa, joka määritellään metodin sisällä kutsutaan paikalliseksi tiedoksi / paikalliseksi muuttujaksi Noppa luokassa muuttuja tulos määritetään toString metodin sisällä – se on pakallinen ko. Metodille ja tulkseen ei voida viitata muualta. Vertaa esimerkiksi taulu-olioiden length attribuuttia, joka on public-tyyppinen ja luokkatasolla

13 Instanssin tieto eli olion tieto
nopanArvo muuttuja Noppa luokassa kutsutaan instanssin tiedoksi sillä jokainen instanssi (olio) joka luodaan omistaa oman version siitä Luokka määrittää tiedon tyypin, mutta ei varaa tiedolle mitään muistitilaa Jokainen kerta kun Noppa olio luodaan, uusi nopanArvo muuttuja luodaan myös Luokan oliot jakavat metodin määritykset, mutta jokaisella oliolla on oma muistiavaruus Tämä on ainoa tapa miten kahdella oliolla voi olla erilaiset tilat

14 Instanssitieto Voimme kuvata kaksi Noppa oliota NopanHeitto ohjelmasta kuten seuraavassa: noppa1 5 nopanArvo noppa2 2 Jokaisella oliolla pitää omaa nopanArvo muuttujaa ja tätä kautta oliolla on oma tila

15 UML kaaviot eli diagrammit
Kuten aikaisemmasta on tuttua, UML tarkoittaa Unified Modeling Languagea UML diagrammit näyttävät luokkien ja olioiden väliset suhteet UML luokkadiagrammi koostuu yhdestä tai useammasta luokasta, joissa jokaisessa on erotetut osiot luokan nimelle, attribuuteille (tiedolle) ja operaatioille (metodeille) Viivat luokkien välillä (luokkakaaviossa) esittävät yhteyssuhteita eli assosiaatioita. Näistä tutustumme seuraaviin (kahteen) tyyppiin: Katkoviivalla varustettu nuoli kertoo, että toinen luokka (siis luokasta tehty olio) käyttää toista (eli kutsuu sen metodeja) – kontrolli siirtyy. Näitä katkoviivanuolia käytämme etupäässä, tosin tutustumme myös koostumus-suhteisiin eli aggregaatioihin (joita ilmaistaan ns. Timanttimerkillä)

16 UML luokkakaaviot UML luokka class diagram HeitäNoppaa ohjelmalle:
+main (args : String[]) : void Noppa -nopanArvo : int +heitä() : int +setNopanArvo (int arvo) : void +getNopanArvo() : int +toString() : String

17 Missä ollaan? Luokan anatomia Kapselointi Metodin anatomia

18 Kapselointi Voimme ottaa yhden kahdesta näkökulmasta tarkastella oliota: sisäinen - luokan muuttujien ja metodien yksityiskohdat, eli luokan määrittäminen ulkoinen - palvelut, jotka olio tarjoaa ja kuinka olio vuorovaikuttaa muiden järjestelmän olioiden kanssa Ulkoisestä näkökulmasta, olio on enkapsuloitu entiteetti (eli kokonaisuus), se tarjoaa joukon määritettyjä palveluita Nämä palvelut määrittävät olion rajapinnan (eli interface), joka näkyy ulospäin

19 Kapselointi Yksi olio (kutsutaan asiakkaksi (client)) voi käyttää toista oliota, jotta voisi tarjota palvelut jotka sen pitää tarjota Olion asiakas voi pyytää ko. olion palveluita (eli kutsua olion metodeja), mutta sen ei pitäisi tietää kuinka ko. palvelut suoritetaan. Vrt. Esim. Coca-Cola automaatin toiminta. Jos käyttäjää ajatellaan oliona, hän haluaa vain Coca-Colaa eikä välittää automaatin sisäisestä toiminnasta. Mikä tahansaa muutos olion tilassa (sen muuttujissa) pitää tehdä olion metodien kautta (eli tavallisesti set ja get metodit) Huomaa myös poikkeukset tästä esim. Taulukko-luokkien length- attribuutti (public) Meidän pitää tehdä vaikeaksi, ellei jopa mahdottomaksi, asiakaan päästä käsiksi olion muuttujiin suoraan (kuten taulukko-olion length) Eli, olioiden pitäisi olla itsehallintoon perustuvia (self-governance)

20 Kapselointi Enkapsuloitua oliota voidaan ajatella mustana laatikkona – sen sisäinen toiminta peitetään asiakkailta Asiakas kutsuu rajapintametodeja (tavalliset public-tyyppiset metodit) – nämä hallitsevat instanssin tietoa Metodit Tieto Asiakas

21 Näkyvyyden muuntelu Javassa, me saavutamme kapselointin käyttämällä sopivia näkyvyysmääritteitä (visibility modifiers) näkyvyysmäärite on Javan varattu sana, joka määrittää tietyn metodin tai muuttujan luonteen final määritettä käytetään vakioiden määrittämiseen (esim. private final EUROTOMARK = 5.94) Javassa on kolme näkyvyyden muuntelumäärettä: public, protected ja private protected määre liittyy periytymiseen, jota käsittelemme opintojaksomme osiossa kolme. Tehtävissä, emme käytä ko. määrettä tässä osiossa.

22 Näkyvyyden määritteet
Luokan osiin (attribuutit tai metodit), jotka määritetään julkisiksi (public visibility) voidaan viitata mistä tahansa käsin Luokan osiin (attribuutit ja metodit), jotka määritetään yksityisiksi (private visibility) voidaan viitata ainoastaan ko. luokan sisältä Luokan osiin (attribuutit ja metodit), joille ei anneta näkyvyyttä (visibility) ollenkaan, annetaan oletusarvoinen näkyvyys (default visibility) ja näihin voidaan viitata mistä tahansa luokasta samassa paketissa

23 Näkyvyyden määrittäminen
Julkiset muuttujat rikkovat kapselointiperiaatetta vastaan, sillä ne mahdollistava sen että asiakas pääse käsiin ja voi voi muutella luokan attribuuttien arvoja Siksi luokan muuttujia ei saisi määrittää julkisen näkyvyyden kanssa (eli siis pitää aina käyttää private sanaa ennen muuttujan nimeä) On hyväksyttävää antaa vakiolle (public final MAX) julkinen näkyvyys, jolloin sitä voidaan käyttää (mutta ei muuttaa) luokan ulkopuolelta Julkiset vakiot eivät riko kapselointiperiaatetta vastaan, sillä vaikka asiakkaalla on pääsy näihin vakioihin, asiakas ei voi muuttaa niiden arvoa (kun final määre käytössä!)

24 Näkyvyyden määrittäminen
Metodit, jotka tarjoavat olion palvelut määritetään julkisen näkyvyyden (public visibility) kanssa, jotta niitä voidaan kutsua asiakkaista käsin Esim. annaCocaCola(1) // määräys Julkisia metodeja kutsutaan myös palvelumetodeiksi (service methods) Metodia, joka luodaan pelkästään auttamaan palvelumetodia kutsutaan tukimetodiksi (esimerkiksi pudotaPullo()) Koska tukimetodia ei kutsuta asiakkaasta käsin, se pitää määrittää tyypillisesti private näkyvyyden kanssa

25 Tukevat luokan muita metodeja palveluja asiakkaille
Näkyvyysmääritteet public private Muuttujat, attribuutit Metodit Rikkovat enkapsulointia Tukevat enkapsulointia Tukevat luokan muita metodeja Tarjoavat palveluja asiakkaille

26 Aksessorit ja mutaattorit – eli getterit ja setterit
Koska instanssitieto on yksityistä (private), luokka yleensä tarjoaa palveluita muuttujien arvojen lukemista ja päivittämistä varten Aksessorimetodi (accessor method) palauttaa muuttujan nykyisen arvon (lukee muuttujan arvon) - kutsutaan myös gettereiksi Mutaattori metodi (mutator method) muuttaa muuttujan arvoa (päivittää muuttujan arvoa) – kutsutaan myös settereiksi Nimet aksessori ja mutaattorimetodeille ovat muotoa getX ja setX, jossa X on arvon nimi (esim. setOppilasNumero(numero) Näitä kutsutaan aksessorin ja mutaattorin sijasta monasti “gettereiksi” ja “settereiksi”

27 Mutaattorin rajoitukset
Mutaattorien käyttö antaa luokan suunnittelijalle mahdollisuuden rajoittaa asiakkaan mahdollisuuksia muutella olion tilaa (muuttujien arvoja suoraan, setteriin voi laittaa esim. tarkistuksen minkälainen luku on kyseessä) Mutaattori suunnitellaan usein niin, että muuttujien arvot voidaan asettaa vain tietyissä rajoissa. Esimerkiksi tilin omistajan nimi voidaan rajata max 50 merkkiin – sillä tietokannassa jossa tietoja lopulta säilytetään on todennäköisesti kokorajoitus Esimerkiksi setNopanArvo mutaattori Noppa luokassa pitäisi rajoittaa niin, että arvo voidaan asettaa ainostaan johonkin tasalukuun sallitulla arvoaluella (tässä 1:stä MAX vakion arvoon asti) Myöhemmin tutustumme tarkemmin siihen miten tällaisia rajoituksia toteutetaan

28 Luokkien kirjoittaminen - this
Muista this-avainsanan käyttö This-sanalla viitataan olion attribuuttiin Ilman this sanaa metodille tulevat parametrit on nimettävä erinimisiksi kuin luokan attribuutit

29 Lisää this-sanasta This-viittaa aina kyseisellä hetkellä käytössä olevaan olioon Koko nykyinen olio voidaan palauttaa kirjoittamalla return(this);

30 toString metodi Pääsääntöisesti kaikille luokille pitää kirjoittaa toString metodi toString konkatenoi Stringiksi olion attribuuttien arvon tällähetkellä Eli kyseessä on ns. olion tilan tulostaminen Ilman toString metodia saadaan oliosta tulostumaan ns. OID numero, joka on muistiosoite viitaten missä itse olio sijaitsee

31 Missä ollaan? Luokan anatomia kapselointi Metodin anatomia

32 Metodin määrittämiset
Katsomme seuraavassa metodin määrittämistä hiukan tarkemmin Metodin määrittely määrää koodin, joka tullaan suorittamaan kun metodia kutsutaan Kun metodia kutsutaan, kontrolli (ns. etenemisrivi) ohjelmassa hyppää ko. Metodiin ja suorittaa ko. metodin koodin. Tämän suorittaminen loppuu kun tullaan return- lauseeseen. Kun tämä valmistuu, kontrolli palaa takaisin sinne mistä metodia kutsuttiin (voi tehdä esim. sijoituksen) ja jatkaa seuraavalta riviltä Metodi voi palauttaa tai olla palauttamatta arvon, riippuen kuinka metodi on määritetty

33 Metodin kontrollivirta
Jos kutsuttu metodi on samassa luokassa tarvitaan vain metodin nimi kutsumiseen munMetodi(); munMetodi laske

34 Metodin kontrollivirta
Kutsuttu metodi on usein osa toista luokkaa tai oliota (siis nimenomaan oliota yleensä, ellei static) olio.teeSe(); main teeSe autaMua autaMua();

35 Metodin headeri Metodin määritys alkaa metodin headerilla
char laske(int num1, int num2, String viesti) metodin nimi parametrilista Parametrilista määrittää jokaisen parametrin tyypin ja nimen Parametrin nimeä metodin määrittelyssä kutsutaan formaaliksi parametriksi. Ko. muuttujat luodaan aivan kuten metodin sisällä luodaan muuttujia. palautus tyyppi

36 Metodin runko Metodin headeria eli otsikkoa seuraa metodin runko (method body). Muista: Headerissa on määritetty myös formaalit parametrit. char laske(int num1, int num2, String viesti) { int sum = num1 + num2; char tulos = viesti.charAt (sum); return(tulos); } sum ja tulos ovat paikallista tietoa tähän metodiin Nämä muuttujat luodaan aina kun tätä metodia kutsutaan, ja ne tuhotaan kun metodin suoritus loppuu Returnissa palautettavan Olion tulee olla palautus- tyyppiä eli samaa kuin metodin headerissa

37 return lause Metodin palautustyyppi määrää minkätyyppisen arvon metodi lähettää takaisin sinne, mistä metodia on kutsuttu Metodilla, joka ei palauta arvoa on void palautustyyppi (metodin formaalissa esittelyssä) return lause määrää mikä arvo metodista palautetaan return(olio); Olion on tässä oltava samaa tyyppiä kuin formaalissa esittelyssä määritetty tyyppi ja kutsumispaikassa olio tulee sijoittaa esim. samantyyppiseen muuttujaan

38 Parametrit Kun metodia kutsutaan, varsinaisten parametrien arvot kutsun yhteydestä kopioidaan formaaleiden parametrien arvoiksi ch = olio.laske (25, count, “Moro"); char laske (int num1, int num2, String viesti) { int sum = num1 + num2; char tulos = viesti.charAt (sum); return tulos; }

39 Paikallinen data eli paikallinen tieto
Kuten olemme huomanneet, paikalliset muuttujat voidaan määrittää metodin sisällä Metodin formaalit parametrit luovat automaattisia paikallisia muuttujia kun metodia kutsutaan Kun metodi lopettaa toimintansa, kaikki paikalliset muuttujat tuhotaan (mukaanlukien formaaleista parametreistä tehdyt muuttujat) Pidä mielessä, että instanssimuuttujat, luokan tasolla määritetyt, ovat olemassa niinkauan kuin olio on olemassa

40 Pankkitiliesimerkki Katsotaan toista esimerkkiä, joka demonstroi toteutusyksityiskohdat luokista ja metodeista Esitämme pankkitilä luokalla, jonka nimi on Tili Pankkitilin tila voi sisältää pankkitilin numeron, saldon tällähetkellä ja tilin omistajan nimen Tilin käyttäytyminen (tai sen palvelut) sisältävät otot ja talletukset sekä koron lisäämisen tilille

41 Testeriohjelmat Testeriohjelma eli ajuriohjelma ajaa toisia, kiinnostavampia osia ohjelmasta Testeriohjelmia käytetään usein testaamaan muista osia ohjelmasta Testeriohjelma sisältää luonnollisesti main- metodin, aloittaa siis ajettavan Transaktion luokka sisältää main metodin, joka ajaa Tili luokan, kokeillen sen palveluita

42 Pankkitili esimerkki tili1 tilNumero 72354 saldo 102.56 nimi tili2
“Matti Nykänen” tili2 69713 tiliNumero 140.00 saldo nimi “Pekka Pere”

43 Pankkitili esimerkki On olemassa joitain parannuksia, joita voidaan tehdä Tili luokkaan Muodolliset getterit ja setterit pitäisi määrittää kaikille muuttujille Joidenkin metodien design voisi olla robustimpi (vankempi), kuten todentaa että määrä parametri nosto metodille on positiivinen saldo - nosto

44 Konstruktorit - lisää Huomaa, että konstruktorilla ei ole palautustyyppiä määritetty metodin headeriin (formaaliin määritykseen) – ei edes void tyyppiä! Yleinen virhe on laittaa konstruktorille palautustyyppi, mikä tekee siitä “tavallisen” metodin, jolla sattuu olemaan sama nimi kuin ko. luokalla Ohjelmoijan ei tarvitse määrittää konstruktoria luokalla (eli oletuskonstruktori on jo olemassa, kyse on sen korvaamisesta) Jokaisella luokalla on valmiiksi Javan tekemä oletuskonstruktori eli oletusmuodostin (default constructor) joka ei ota parametrejä (muista kuitenkin myös konstruktorin ylikuormittaminen) public Pvm() // esimerkki oletuskonstruktorista

45 Konstruktoreista Synonyymi konstruktori-sanalle on muodostin
On tärkeää osata seuraavat käsitteet: Oletuskonstruktori (oletusmuodostin) Korvaa Javan oletusarvoisen konstruktorin – ilman parametrejä() olevan konstruktorin Parametrillinen konstruktori (parametrillinen muodostin) Saa vaihtelevan määrän parametrejä Kopiokonstruktori (kopiomuodostin) Saa parametrinä oman luokan olion ja kopio olion nykyiseen olioon (eli tekee kopin)

46 Missä ollaan? Luokan anatomia kapselointi Metodin anatomia
Selvisimme tästä, seuraavaksi yhteenveto

47 Yhteenveto Tutustuimme Luokan määrittämiseen
Instanssidataan (attribuutit) kapselointi ja Java määreet (private ja public) Metodin määrittäminen ja parametrien välittäminen Konstruktorit

48 Lähteet Lewis & Loftus: Java Software Solutions kalvot


Lataa ppt "Olio-ohjelmointi: Luokkien kirjoittaminen"

Samankaltaiset esitykset


Iklan oleh Google