Informaatioverkostot: Studio 1 Luentomateriaali - PowerPoint PPT Presentation

1 / 75
About This Presentation
Title:

Informaatioverkostot: Studio 1 Luentomateriaali

Description:

muuttujat taulukot merkkijonot silmukat polymorfismi poikkeukset java-api tietovirrat swing sovelmat 2d-grafiikka s ikeet ja swing uml-kaaviot javadoc pakkaukset – PowerPoint PPT presentation

Number of Views:53
Avg rating:3.0/5.0
Slides: 76
Provided by: hut96
Category:

less

Transcript and Presenter's Notes

Title: Informaatioverkostot: Studio 1 Luentomateriaali


1
Informaatioverkostot Studio 1Luentomateriaali
  • Janne Käki
  • 2006

5 11 17 23
40 45 50 60
28 33 35 37
63 64 66 70
2
Muutama perusasia
  • Tietokone tekee juuri (ja vain) sen, mitä
    käsketään.
  • Tietokone ymmärtää vain syntaksia (sanojen
    kirjoitusasua), ei semantiikkaa (sanojen
    merkitystä).
  • Muuttujat ja metodit voi tietokoneen puolesta
    nimetä (melkein) ihan miten vaan, olennaista on
    vain, että samasta muuttujasta tai metodista
    käytetään johdonmukaisesti samaa nimeä.
  • Java-kielessä on kuitenkin joitakin kymmeniä
    avainsanoja (public, private, int, void, true,
    null, return, . . .), jotka on varattu tiettyyn
    käyttöön. Näitä ei siis voi valita muuttujien
    nimiksi.
  • Se, että muuttujat ja metodit nimetään fiksusti
    ja käyttötarkoitusta kuvaavasti, on tärkeää
    nimenomaan (ja vain) koodia lukevan ihmisen
    kannalta.
  • Ohjelman suoritus on normaalisti (virheettömänä)
    täysin näkymätöntä.
  • Siksi tarvitaan tulostuksia, jotta saisimme
    käsityksen siitä, mitä ohjelmassa tapahtuu mitä
    paremmat tulostukset, sitä parempi käsitys.

3
Sijoituslause
sijoitusoperaattori (ei yhtäsuuruusmerkki!)
  • int luku (5 4) 8 - 7
  • laskuri laskuri 1

1. Selvitetään oikeanpuoleisen lausekkeen arvo.
2. Määritellään uusi kokonaislukutyyppinen
muuttuja nimeltä luku. 3. Sijoitetaan kohdassa 1
laskettu arvo kohdassa 2 määriteltyyn muuttujaan.
1. Lasketaan yhteen laskurin nykyinen arvo ja
yksi.
2. Sijoitetaan tämä arvo laskurin uudeksi
arvoksi. (Koska laskurimuuttuja on jo
entuudestaan olemassa, sitä ei siis ole syytä
määritellä uudelleen, joten emme käytä sanaa int.)
4
Palauttaminen vs. tulostaminen
Metodi, joka palauttaa tekstin böö public
String palautaBöö() return böö
Metodi, joka tulostaa tekstin böö public
void tulostaBöö() System.out.println(böö)

paluuarvon tyyppi
ei palauta mitään
antaa palautettavan arvon käyttöön sille, joka
metodia kutsui
tuottaa tekstin näytölle
String bööTeksti palautaBöö() System.out.print
ln(bööTeksti)
böö
5
Oliokohtaiset Luokkakohtaiset (static)
Attribuutit Luokan yksittäisen ilmentymän eli olion ominaisuudet. Määrittelevät olion tilan. Yleensä yksityisiä, eli vain oliolla itsellään on suora pääsy käsiksi attribuuttien arvoihin. Ominaisuuksia, jotka ovat kaikkien luokasta luotujen olioiden yhteisessä käytössä. Usein julkisia, eli kuka tahansa näkee nämä. Yleensä lisäksi vakioita, eli niille asetetaan tietty arvo, jota ei jälkeenpäin pysty muuttamaan.
Metodit Luokan yksittäisen ilmentymän eli olion toiminnot, mitä olio osaa. Antavat mahdollisuuden saada tietoja olion tilasta ja muuttaa sitä. (Olion metodien tehtävänä on siis tarjota rajapinta, jonka avulla ulkopuolinenkin voi kysyä ja jopa muokata olion attribuuttien arvoja.) Metodeja, jotka eivät kuulu millekään yksittäiselle oliolle. (Niinpä sana this ei merkitse tällaisessa metodissa mitään.) Pääohjelmametodi on aina tällainen. Jos siellä halutaan testata jotakin yksittäisen olion metodia, tällainen olio pitää ensin luoda ja laittaa talteen johonkin muuttujaan.
6
Tiedon abstraktiotasoja
kokoelmatnimetty joukko olioita
oliotnimetty joukko muuttujia (ja operaatioita)
Javan fokus
muuttujatnimetty tietyntyyppisen tiedon
muistipaikka
muistipaikatjoukko bittejä, joilla on yksi osoite
bititnollia tai ykkösiä
7
Erilaisia muuttujia
attribuutit määrittävät olion tilan eli ominaisuuksien arvot
attribuutit määrittävät olion tilan eli ominaisuuksien arvot
parametritantavat metodille sen suorituksen kannalta tarpeelliset lähtötiedot
parametritantavat metodille sen suorituksen kannalta tarpeelliset lähtötiedot
apumuuttujat mahdollistavat jonkin arvon muistamisen niin kauan kuin sitä tarvitaan
apumuuttujat mahdollistavat jonkin arvon muistamisen niin kauan kuin sitä tarvitaan
  • public class Mursu
  • private String nimi
  • private int nopeus
  • public Mursu(String nimi, int nopeus)
  • this.nimi nimi
  • this.nopeus nopeus
  • public double liiku(double aika)
  • double matka aika this.nopeus
  • System.out.println(nimi lyllersi matka
    km.)
  • return matka

8
Muuttujista
  • Muuttujan määrittely (eli esittely) nimetään
    tietolokero ja kerrotaan, minkä tyyppistä tietoa
    se voi sisältää.
  • String brutaaliSolvaus
  • int vihreidenPingviinienLukumaara
  • Muuttujan alustus sijoitetaan muuttujaan (sen
    historian ensimmäinen) arvo.
  • brutaaliSolvaus hähä mogari
  • Voidaan tehdä myös suoraan määrittelyn
    yhteydessäString brutaalimpiSolvaus luetaan
    sitä APIa
  • Muuttujan arvon lukeminen käytetään muuttujaa
    missä tahansa muualla kuin sijoituslauseen
    vasemmalla puolella.
  • System.out.println(brutaalimpiSolvaus)
  • if (vihreidenPingviinienLukumaara gt 1)
  • Ei saa tehdä alustamattomalle muuttujalle, muuten
    kääntäjää alkaa pelottaa. (Variable might not
    have been initialized.)
  • Attribuuteilla on aina tietty alkuarvo
    automaattisesti (numeromuuttujilla nolla,
    booleaneilla false, oliomuuttujilla null), joten
    niiden alustaminen ei ole välttämätöntä ennen
    muuttujan käyttämistä yleensä toki
    suositeltavaa.

9
Tietotyypeistä
alkeistyypit kokonaisluku byte
alkeistyypit kokonaisluku short
alkeistyypit kokonaisluku int
alkeistyypit kokonaisluku long
alkeistyypit desimaaliluku (liukuluku) float
alkeistyypit desimaaliluku (liukuluku) double
alkeistyypit totuusarvo boolean
alkeistyypit merkki char
viittaustyypit merkkijono String
viittaustyypit alkeistyyppien kääreet Integer, Double, Boolean, Character, ...
viittaustyypit taulukot int , double , Object , Karttaruutu , ...
viittaustyypit muut oliotyypit Object, Random, HashSet, Pelotteluesine, ...
olioita
10
Viittaustyyppiset muuttujat
  • Olio on kuin ilmapallo.
  • Oliomuuttujat ovat viittauksia kuin naruja,
    joiden päässä se ilmapallo on.
  • Sama olioilmapallo voi olla useamman narun
    päässä. Siihen voidaan vaikuttaa (eli sen
    metodeita kutsua) kaikkia naruja pitkin, ja
    kaikki kutsut muokkaavat yhtä ja samaa oliota.
  • Kun oliomuuttuja lakkaa olemasta tai saa uuden
    arvon, yksi naru katkeaa.
  • Kun olio ei ole enää yhdenkään narun päässä
    kiinni, se karkaa stratosfääriin (eli Javan
    automaattinen roskienkerääjä tulee ja syö sen).

11
Klassinen for-lause
for (int i 0 i lt 3 i) ...
ei
onkoehtotosi?
for-lauseen jälkeinen elämä
alustus-lause
suoritettavatlauseet
kyllä
kasvatus-lause
12
Tällainen for-lause...
for (int i 0 i lt 3 i) ...
...vastaa while-lauseella toteutettua rakennetta
int i 0 while (i lt 3) ...
i
Mikä merkityson ulommillaaaltosuluilla?
13
Iteroiva for-lause
public void tulostaNimet(SetltOlentogt olennot)
for (Olento o olennot)
System.out.println(o.annaNimi())
  • Käy läpi kaikki tiettyyn kokoelmaan sisältyvät
    oliot.
  • Kukin kokoelman olio sijoitetaan siis vuorollaan
    for-lauseen määrittelemään muuttujaan ja siihen
    sovelletaan aaltosulkujen sisällä olevia
    lauseita.
  • Läpikäyntijärjestys riippuu kokoelmasta.
    Listoilla se on määrätty, joukoilla (Set) yleensä
    määrittelemätön, mutta ei kuitenkaan aidosti
    satunnainen.
  • Kokoelman sisältöä ei saa muuttaa (lisätä tai
    poistaa olioita) kesken iteroinnin, muuten seuraa
    virhe nimeltä ConcurrentModificationException.

14
public void tulostaNimet(SetltOlentogt olennot)
String nimet for (Olento o olennot)
nimet o.annaNimi() ,
System.out.println(nimet)
Miten pääsemme eroon ylimääräisestä pilkusta?
Arska, Pena, Mats, Rauski,
Tulostaa
public void tulostaNimet(SetltOlentogt olennot)
String nimet int otuslaskuri 0
for (Olento o olennot) nimet
o.annaNimi() if (otuslaskuri lt
olennot.size()-1) nimet ,
otuslaskuri
System.out.println(nimet)
15
Iteraattori
Vanha tuttu iteroiva for-looppi...
Kokoelman on toteutettava rajapintaIterableltTgt,
joka määrittelee metodin public IteratorltTgt
iterator().
  • for (Olio o kokoelma)
  • System.out.println(o)

...toimii pinnan alla itse asiassa
iteraattoriolion avulla.Sama looppi hieman
toisin kirjoitettuna
IteratorltOliogt iter kokoelma.iterator() while
(iter.hasNext()) Olio o iter.next()
System.out.println(o)
Myös IteratorltTgt on itse asiassa
rajapinta.Iteraattorin metodi next() palauttaa
ja poistaa iteraattorista, ei
iteroitavastakokoelmasta järjestyksessä
seuraavanelementin. Metodi hasNext()
kertoo,vieläkö elementtejä on jäljellä.
16
Iteraattori
  • Iteroimisessa on vaaransa. Metodi next() voi
    heittää poikkeuksia...
  • NoSuchElementException, jos elementtejä ei enää
    ole. Vältettävissä huolellisella
    hasNext()-metodin käytöllä.
  • ConcurrentModificationException, jos iteroitava
    kokoelma on muuttunut iteraattorin luomisen
    jälkeen. Uusia elementtejä ei siis voi kesken
    iteroinnin lisätä, ellei iterointia tämän jälkeen
    keskeytä.Elementtien poistaminen on luvallista
    iteroinnin lomassa vain iteraattori-olion
    metodilla remove(), joka poistaa viimeisimmän
    next()-metodin palauttaman elementin, myös
    iteroitavasta kokoelmasta.
  • Iteraattori siis antaa luvan myös elementtien
    poistamiseen kokoelmasta (periaatteessa oma
    iteraattoriluokka voidaan kuitenkin toteuttaa
    myös niin, ettei remove()-metodi tee mitään).
    Aina ulkopuoliselle käyttäjälle ei haluta jättää
    tällaista mahdollisuutta, jolloin voi olla syytä
    harkita toisenlaisen rajapinnan tarjoamista
    kokoelman läpikäyntiin.

17
Taulukko
Taulukkomuuttujan määrittely ja alustaminen ns.
taulukon alustajalla
0 1 2 3 4 5 6
9 14 2 7 2 0 22
int taulu 9, 14, 2, 7, 2, 0, 22
Taulukon indeksointi ja sen alkioiden arvojen
asettaminen
taulu0 1taulu2 100taulutaulu.length-1
8
0 1 2 3 4 5 6
1 14 100 7 2 0 8
Uuden, tyhjän taulukon luonti new-operaattorilla
0 1 2 3 4
0 0 0 0 0
taulu new int5
Taulukotkin ovat olioita. Huomaa, että taulukon
koko on taulukko-olion, ei taulukkomuuttujan
ominaisuus. (Samaan muuttujaan voi sijoittaa
minkä kokoisen taulukon tahansa.) Taulukon
tietotyyppi on sen sijaan myös taulukkomuuttujan
ominaisuus.
18
Laskurilla varustettu for-silmukka on kuin luotu
taulukon läpikäymiseen, esimerkiksi seuraavassa
fiktiivisessä Olento-luokan metodissa
public void kauhistuHirviolaumaa(Olento
hirviot) for (int i 0 i lt
hirviot.length i) hirvioti.pelottel
e(this)
this viittaaaina siihen olioon, jonkametodista
on kyse.Sitä voi käyttää myössellaisenaan,
esimerkiksiparametrina jollekintoiselle
metodille.
Muista, ettätaulukon indeksitalkavat nollasta
japäättyvät yhtäpienempään kuintaulukon koko.
hirvioti viittaavuorollaan aina
yhteentaulukon alkioon,siis Olento-tyyppiseenol
ioon (ellei kyseinenalkio ole null).
19
Jos määrittelemme seuraavasti
int tauluA int tauluB null int tauluC
new int5 Pelotteluesine tauluD new
Pelotteluesine1000
ja sen jälkeen yritämme seuraavia asioita, mikään
niistä ei onnistu. Miksi?
tauluA0 49 tauluB0 88 tauluC5
31 tauluC2 4.86 tauluA new
double10 tauluB tauluA tauluD666.annaPelot
tavuus()
Inspired by http//www.cs.helsinki.fi/u/wikla/Ohj
elmointi/Sisalto/3/Taulukot.html2
20
Kaksiulotteinen taulukkoeli taulukoita taulukossa
Luodaan 2D-taulukko eli matriisi, jossa on neljä
riviä ja viisi saraketta
0 1 2 3 4

0
1
2
3
Olento otusruudukko new
Olento45 otusruudukko21 new
Olento(Rauski, 100)
0 1 2 3 4

Itse asiassa loimme yhden nelipaikkaisen
taulukon, jonka alkioiden tietotyyppi on
Olento. Se sisältää siis neljä yksiulotteista,
viisipaikkaista olentotaulukkoa. Nämä taulukot
ovat aluksi tyhjiä, eli niiden jokainen alkio on
null. Voimme sijoittaa ruudukkoon uusia arvoja
kertomalla, mihin alitaulukkoon ja mihin lokeroon
siellä kyseinen arvo sijoitetaan
0 1 2 3 4

0 1 2 3 4

21
2D-taulukon rivien ei välttämättä tarvitse olla
samanpituisia jokainen alitaulukkohan on
yksilöllinen olio, jonka pituus voi olla mitä
vain
0 1 2 3 4

0
1
2
3
Olento otusruudukko new Olento4
0 1 2

Huomaa tyhjät jälkimmäiset hakasulut. Tässä
luotiin tyhjä nelipaikkainen taulukko, johon voi
sijoittaa Olento-taulukoita. Näitä
alitaulukkoja ei kuitenkaan vielä ole olemassa,
ne on luotava nyt erikseen.
0

otusruudukko0 new Olento5 otusruudukko1
new Olento3 otusruudukko2 new
Olento1 otusruudukko3 new
Olento4 otusruudukko33 new
Olento(Rauski, 100)
0 1 2 3

22
for-lauseita voi käyttää myös sisäkkäin. Kaksiulot
teisen taulukon läpikäynnissä tämä on usein
tarpeen
String ruudut new String55 for (int i
0 i lt ruudut.length i) for (int j
0 j lt ruuduti.length j)
ruudutij i , j
0, 0 0, 1 0, 2 0, 3 0, 4
1, 0 1, 1 1, 2 1, 3 1, 4
2, 0 2, 1 2, 2 2, 3 2, 4
3, 0 3, 1 3, 2 3, 3 3, 4
4, 0 4, 1 4, 2 4, 3 4, 4
23
Merkkijonojen vertailu
String a "kaikki on mahdollista" String b
"kaikki on mahdollista"
System.out.println(a b) b new
String("kaikki on mahdollista")
System.out.println(a b) System.out.println(a.
equals(b)) System.out.println(a b.intern())
true false true true
Esimerkit Ville Sundberg
24
EI NÄIN
if (nimi Rauski)
VAAN NÄIN
if (nimi.equals(Rauski))
TAI JOS KIRJAIN-KOOLLA EI OLE MERKITYSTÄ
if (nimi.equalsIgnoreCase(RAUSKI))
25
Merkkijonon paloittelu
String lause Kivet on tosi jänniä. String
sanat lause.split( )
sanat0 sanat1 sanat2 sanat3
Kivet on tosi jänniä.
26
Merkkijonon tulkinta luvuksi
  • Integer.parseInt(String merkkijono)
  • Integer-luokan staattinen metodi
  • yrittää tulkita merkkijonon kokonaisluvuksi
  • heittää poikkeuksen NumberFormatException, jos
    merkkijono ei esitä puhdasta kokonaislukua
    (varauduttava aina tähän mahdollisuuteen)
  • Double.parseDouble(String merkkijono)
  • Double-luokan staattinen metodi, muuten sama kuin
    yllä mutta tulkitsee merkkijonoja
    desimaaliluvuiksi (desimaali-erottimena
    oletusarvoisesti piste)

27
  • String-luokassa lisäksi mm. metodit
  • String substring(int alku, int loppu)
  • palauttaa osamerkkijonon väliltä alku loppu-1
  • int indexOf(String osamerkkijono)
  • palauttaa indeksin, josta etsittävä osamerkkijono
    (ensimmäinen löytynyt) alkaa
  • jos osamerkkijonoa ei löydy, palauttaa arvon 1
  • String trim()
  • palauttaa merkkijonon kopion, jonka alusta ja
    lopusta on poistettu mahdolliset välilyönnit
  • String toLowerCase()
  • palauttaa merkkijonon kopion, jonka kaikki ISOT
    KIRJAIMET on muutettu pieniksi kirjaimiksi
    (toUpperCase() tekee saman toisinpäin)
  • String toString()
  • D

Luokka String on arvo-keskeinen String-olion
metodit eivät muuta kysei-sen olion tilaa
mitenkään. Jos metodi tekee muutoksia, se
palauttaa kopion alku-peräisestä uuden olion.
28
Halutaan luoda uusi Pelotteluesine...
Kun luodaan uutta Pelotteluesinettä, on sille
ensin rakennettava yläluokkien määrittelemä
perusta alustettava ne ominaisuudet, jotka
sille kuuluvat 1) Objectina ja 2) Esineenä.
public Pelotteluesine(String nimi, double
paino, int pelottavuus) super(nimi,
paino) this.pelottavuus pelottavuus
public Esine(String nimi, double paino)
super() this.nimi nimi this.paino
paino public Object() ...
...mutta ennen pelotteluesineen oman
pelottavuus-ominaisuuden alustusta on
varmistettava, että perustana on oikeaoppinen
Esine. Siksi ihan aluksi kutsutaan Esine-luokan
luontimetodia...
Pelotteluesine private int pelottavuus public
Pelotteluesine(String nimi,double paino, int
pelottavuus)
Esine private String nimiprivate double
paino public Esine(String nimi, double paino)
...jonka aluksi puolestaan kutsutaan vielä
Object-luokan konstruktoria. (Tässä super()ia ei
olisi pakko kirjoittaa, koska nyt yläluokan
luontimetodille ei tarvitse antaa parametreja.
Esineelle sen sijaan täytyi.)
ominaisuuksien määrä
Object public Object()
29
Metodin kuormittaminen(overloading)
  • Samannimisestä metodista on määritelty samassa
    luokassa (tai samassa yli- ja aliluokkien
    jatkumossa) useita versioita, joista valitaan
    suoritettavaksi yksi sen perusteella, mitä
    parametreja metodikutsussa on annettu.
  • Metodikutsu sidotaan suoritettavaan metodiin
    metodin nimen sekä parametrien tyyppien ja
    järjestyksen perusteella. (Sen sijaan esimerkiksi
    parametrimuuttujien nimillä ei ole mitään
    merkitystä.Ei myöskään sillä, minkä tyyppisiä
    arvoja metodin eri versiot palauttavat.)
  • Metodikutsujen on oltava yksiselitteisiä, eli ei
    saa olla epäselvää, mikä vaihtoehtoisista
    tietynnimisen metodin versioista nyt suoritetaan

?
public void metodi(Object o, String s)
... public void metodi(String s, Object o)
...
metodi(nuuh, nuuh)
?
metodi(nuuh, (Object) nuuh)
30
Metodin korvaaminen(overriding)
  • Aliluokka määrittelee yliluokassa määritellyn
    metodin toteutuksen kokonaan uudelleen. Korvaavan
    metodin puumerkki on täsmälleen sama kuin
    alkuperäisen, eli metodeilla on sama nimi,
    samanlainen parametrilista (tyypit ja järjestys)
    ja sama paluuarvon tyyppi.
  • Voidaan merkitä aliluokkaan kirjoittamalla
    metodin yläpuolelle erityinen _at_Override-tägi. Ei
    pakollista, mutta parantaa luettavuutta.
  • Metodin uusi versio EI saa
  • muuttaa paluuarvon tyyppiä,
  • rajata näkyvyyttä alkuperäistä suppeammaksi
    (laajentaa sen sijaan saa),
  • heittää sellaisia poikkeuksia joita alkuperäinen
    ei määritellyt heittävänsä (sen sijaan uusi
    versio voi mainiosti olla heittämättä joitakin
    poikkeuksia joita alkuperäinen metodi heitti).
  • Kun luokan A metodi x() on korvattu aliluokassa B
    metodilla x(), niin alkuperäistä metodia voi
    kutsua luokan B oliolle vain olio itse
    notaatiolla super.x(). Muut kutsut johtavat aina
    luokassa B määritellyn metodin suorittamiseen.

31
Metodien staattinen ja dynaaminen sidonta
Otus eka new Otus() Otus toka new
PäheäOtus() PäheäOtus kolmas new PäheäOtus()
Olkoon PäheäOtus luokan Otus aliluokka.
Otus-luokassa on määritelty tylsä metodi
eksistoi(), jonka PäheäOtus on korvannut uudella
päheämmällä versiolla. Lisäksi PäheäOtus-luokassa
on täysin uusi, ennen näkemätön metodi
kelaaSunLaatuas(). PäheälleOtukselle, joka on
sijoitettu Otus-tyyppiseen muuttujaan, voidaan
kutsua ainoastaan Otus-luokan metodeja. Sanotaan,
että kyseisen olion staattinen tyyppi on Otus.
Vaikka olio siis osaisi myös kelata laatuaan,
sitä ei voi tuon muuttujan kautta käskeä niin
tekemään. Sopivalla tyyppimuunnoksella staattinen
tyyppi voidaan kuitenkin saattaa sellaiseksi,
että tuokin metodi on käytössä. Sen sijaan
muuttujan staattinen tyyppi Otus antaa toki
meille luvan kutsua oliollemme metodia
eksistoi(). Tällöin metodikutsu sidotaan
kuitenkin aina olion todelliseen, dynaamiseen
tyyppiin, joka tässä tapauksessa on PäheäOtus.
Hämmästykseksemme tylsässä Otus-laatikossa
piileksinyt olio alkaakin siis eksistoida hyvin
päheästi, kun käskytämme sitä tuollaisella
metodikutsulla. Mitenkään emme pysty käskemään
tuota oliota käyttäytymään siten kuin puhdas Otus
käyttäytyisi, ellei se sitten itse päätä
suorittaa tuota metodia kutsulla
super.eksistoi(). Staattinen tyyppi siis sanelee
sen, mitkä metodikutsut muuttujaan sijoitetulle
oliolle ovat ylipäänsä luvallisia. Dynaaminen
tyyppi (joka ei olion elinaikana muutu) taas
määrää, mitä koodia oliolle tehtyjen
metodikutsujen seurauksena todella suoritetaan.
)
D
eka
toka
D
kolmas
32
Rajapinnat
Rajapinta eli liittymä (engl. interface) on
luokka, joka määrittelee olion käyttöliittymän
(tai jonkin osa-alueen siitä). Rajapinta toisin
sanoen määrittelee yhden tai useamman metodin,
jotka tarjoavat tietyn toiminnallisuuden. Ja
tarkemmin sanoen se vain määrittelee nämä
metodit, ei toteuta niitä (eikä ota kantaa
siihen, millaisten teknisten yksityiskohtien
avulla niiden toiminnallisuus toteutetaan). Rajapi
nta on toisin sanoen kuin abstrakti luokka, joka
sisältää vain abstrakteja metodeja (siis metodeja
ilman toteutusta, eli tavallaan vaatimuksia
aliluokille tietynlaisten metodien
toteuttamisesta). Mutta siinä missä Java-luokalla
voi olla aina vain yksi suoranainen yläluokka
(abstrakti tai ei), voi sama luokka toteuttaa
yhden, kaksi, kolme tai miljoona rajapintaa.
Toteuttaminen tarkoittaa sitä, että luokkaan on
laadittu käytännön toteutus kaikille näissä
rajapinnoissa määritellyille metodeille ja
lisäksi toteuttami-sesta on kerrottu avainsanan
implements avulla.
1. Rajapintaluokka määrittelee tietyn
toiminnallisuuden.
2. Konkreettiset luokat toteuttavat rajapinnan,
kukin omalla tavallaan.
3. Toinen luokka voi käyttää kaikkia näitä
luokkia rajapinnan edustajina, yhteisten
ominaisuuksien pohjalta.
33
Poikkeukset
Tähän asti olemme tottuneet siihen, että metodin
paluuarvo (true tai false, olio tai null) riittää
kertomaan, onnistuiko metodi tehtävässään vai
ei. Mutta millainen paluuarvo pystyisi
ilmaisemaan, että jäimme kiinni varastaessamme
päärynää? Javan poikkeukset (engl. exceptions)
ovat ikään kuin vaihtoehtoja metodien
normaaleille paluuarvoille. Tyypillisesti ne
kertovat, että metodissa tapahtui odottamaton
virhe. Poikkeusten yhteydessä ei puhuta
palauttamisesta, vaan heittämisestä.
public Paaryna varastaPaaryna() throws
KaameaPoikkeus if (vartija.onVahdissa()
!vartija.nukkuu()) KaameaPoikkeus
poikkeus new KaameaPoikkeus("Kiinni
jäit, hähä!") throw poikkeus
else return paarynapuu.annaPaaryna()

public void eleleVaarallistaElamaa() try
// VOI HEITTÄÄ POIKKEUKSEN
Paaryna saalis this.varastaPaaryna()
this.syo(saalis) catch (KaameaPoikkeus
poikkeus) System.out.println(poikkeus)
this.karsiRangaistus() finally
this.jatkaElamaaEntiseenTapaan()

Monet Javan valmiit poikkeukset (ja tyypillisesti
kaikki itse laaditut) täytyy käsitellä. Toisin
sanoen jos on olemassa vaara (todellinen tai edes
teoreettinen), että tietyn metodin kutsusta
aiheutuu poikkeus, tämän poikkeuksen
mahdollisuuteen tulee varautua ns.
try-catch-rakenteen avulla. Try-osioon
sijoitetaan se metodikutsu, josta
potentiaalisesti voi aiheutua poikkeus, sekä
kaikki se mitä onnistuneesta yrityksestä suoraan
seuraa. Catch-osiossa puolestaan yleensä
reagoidaan jollain tapaa yrityksen
epäonnistumiseen. Finally-osio ei ole pakollinen.
Se suoritetaan sekä onnistuneen että
epäonnistuneen kokeilun lopuksi.
34
Erilaisia poikkeusluokkia
RuntimeException
...näitä ei tarvitse käsitellä.
Tarvitsee käsitellä, paitsi...
Throwable
Kaikkien poikkeus-luokkien yläluokka. (Nimestään
huolimatta ei siis rajapinta.)
Ei tarvitse käsitellä.
35
Keskeisimmät Java-APIn pakkaukset
API Application Programming Interface eli
sovellusohjelmointirajapinta (!) pakkaus (engl.
package) tapa koota samaan asiaan liittyviä
luokkia yhteen
  • java.lang
  • pari aivan keskeistä luokkaa, kuten Object,
    String ja Math
  • alkeistyyppien kääreluokat (Integer, Double,
    Boolean, Character, ...)
  • useimmat poikkeus- (Exception) ja virheluokat
    (Error)
  • aina käytössä, ei tarvitse importoida!
  • java.util
  • kokoelmarajapinnat (Collection, Set, List, Map)
    ja niiden toteutukset (HashSet, Vector,
    ArrayList, HashMap, ...)
  • kirjastoluokat Arrays ja Collections
  • välineitä päiväysten ja kellonaikojen
    käsittelyyn Date, Calendar, TimeZone
  • pari muuta hyödyllistä Random, Timer, Scanner
  • java.io
  • välineet näppäimistön ja tiedostojen lukemiseen
    (erilaiset InputStream- ja Reader-luokat) sekä
    näytölle ja tiedostoon kirjoittamiseen
    (OutputStream- ja Writer-luokat)
  • java.net
  • välineet verkkoyhteyksien muodostamiseen
  • java.awt
  • AWT-luokkakirjasto (Abstract Windowing Toolkit),
    Javan vanhempi kalusto graafisten
    käyttöliittymien toteutukseen
  • javax.swing
  • Swing-luokkakirjasto, uudemmat välineet
    graafisten käyttöliittymien tekemiseen

36
Luetaan sitä APIa!Mutta miten?
Java-ohjelmoinnissa monien ongelmien ratkaisu käy
seuraavaan tapaan
  1. Etsi APIsta oikea luokka haluamasi asian
    tekemiseen.
  2. Etsi luokasta metodi, jolla sen saa tekemään tuon
    asian.
  3. Selvitä, miten kyseistä metodia käytetään.

APIn lukemisessa on kuitenkin muutama
sudenkuoppa, joita kannattaa varoa
  • Varmista, että olet tekemisissä oikean luokan
    kanssa (tsekkaa myös, missä pakkauksessa se on).
    Esimerkiksi java.util.List ja java.awt.List ovat
    kaksi täysin erilaista luokkaa, jotka menevät
    helposti sekaisin.
  • Katso, mistä tutkimasi luokka periytyy.
    Yläluokista voi päätellä paljon siitä, mitä
    luokka osaa omien metodiensa lisäksi tehdä.
    Luokan omassa Method Summary -listassa ei
    mainita yläluokilta perittyjä metodeja, mutta
    luokalla on luonnollisesti myös ne
    käytettävissään. (Ne luetellaan lyhyesti tuon
    listan alapuolella.)
  • Joistakin metodeista on tarjolla useampi
    kuormitettu (engl. overloaded) versio, eli
    samanniminen metodi erilaisilla
    parametrivaihtoehdoilla. Osa näistä on
    suora-viivaisempia käyttää, toiset tarjoavat
    mahdollisuuden hyvinkin monimutkaisiin säätöihin.
    Valitse oikea metodi tarpeesi mukaan, säästyt
    turhalta säätämiseltä. )

37
Tietovirrat
Tavuvirta Merkkivirta
Syöttö (input) java.io.InputStream java.io.Reader
Tulostus (output) java.io.OutputStream java.io.Writer

38
Näppäimistön lukeminen
tavut
11101011
merkit
01001110
b
r
merkkijonot
ö
m
mene avantoon
katso olentoa 4
39
BufferedReader lukija new BufferedReader(
new InputStreamReader(System.in))
BufferedReader
InputStreamReader
InputStream (System.in)
?
IOException (tietovirtahepo) vaanii kaikissa
tietovirroissa
40
Graafisen Java-ohjelman osat
näkyvät osat näkyvät osat näkymättömät osat näkymättömät osat näkymättömät osat
Komponentit Säiliöt Asettelijat Tapahtumat ja kuuntelijat Muut apuluokat
pakkaus javax.swing javax.swing java.awt java.awt.eventjavax.swing.event java.awtjavax.swing.border
tärkeitäesimerkki-luokkia JButton JLabel JTextField JMenuItem JComboBox ... ja monta muuta JFrame JApplet JDialog JPanel JScrollPane JSplitPane FlowLayout BorderLayout GridBagLayout GridLayout BoxLayout CardLayout ActionEventActionListener MouseEventMouseListener ChangeEventChangeListener ... ja monia muita Color Dimension Font GridBagConstraints Insets Border (Swing)
käyttö-tarkoitus pähkinän-kuoressa Käyttöliittymän näkyvät rakennuspalikat, vuoro-vaikutuksen välineet, affordanssit. Esittävät tietoa käyttä-jän ymmärtämässä muodossa sekä tarjoa-vat mahdollisuuksia ohjelman tilan muutta-miseen. Komponentteja, jotka sisältävät toisia kompo-nentteja. Ylimmän tason (top level) säiliöt tulevat toimeen omillaan, eli sellainen muodostaa käyttöliittymän rungon. Alemman tason säiliöitä (kuten JPanel) voi lisätä myös toisiin säiliöihin. Määrittävät, miten tietyn säiliön sisältö (eli siihen lisättävät kompo-nentit) asetellaan suhteessa säiliöön ja toisiinsa. Se, miten (ts. minkä-laisin parametrein) komponentit lisätään säiliöön, riippuu käyte-tyn asettelijan tyypistä. Vuorovaikutus-mekanismien perusta. Käyttäessään jotakin komponenttia käyttäjä aiheuttaa tapahtuman, jonka komponentti lähettää tuntemilleen kyseisen tapahtuma-tyypin kuuntelijoille. Nämä reagoivat siihen suorittamalla jonkin sopivan toiminnon. Kuvaavat abstraktilla tasolla komponenttien tiettyjä näkyviä ominaisuuksia, kuten väriä, kokoa, kehystä tai asettelua. Annetaan tyypillisesti parametrina sopivalle komponenttiolion metodille, kun halutaan asettaa komponentille kyseinen ominaisuus.
top level
41
Tapahtumapohjainen ohjelmointi
ohjelman käynnistys
käyttöliittymän alustus
Tapahtuman kuuntelija(t)
tapahtuman odottelu
42
GridBagConstraints
anchorkomponentin sijainti solunsisällä
(CENTER, NORTH,EAST, SOUTHWEST, jne.)
GridBagConstraints c new GridBagConstraints(
0, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH, new Insets(5, 2,
5, 2), 0, 0)
gridx ja gridykomponentin sijainti-koordinaatit
gridissä(vasemmalta ylhäältä luettuna)
fillkuinka komponentti täyttääsolunsa
(HORIZONTAL,VERTICAL, BOTH tai NONE)
gridwidth ja gridheightkomponentin leveys ja
korkeus(riveissä ja sarakkeissa)
insetsmontako pikseliätyhjää
tilaakomponentinympärille jätetään(ylös,
vasemmalle,alas, oikealle)
ipadx ja ipadypaljonko tyhjää
reunusta(paddingia) kompo-nentin sisään
jätetäänsen minimikoossa
weightx ja weightykomponentin
suhteellinenpainoarvo (0.01.0)säiliötä
täytettäessä
43
GridBagLayout
JPanel paneeli new JPanel( new
GridBagLayout()) JTextField kenttä new
JTextField() GridBagConstraints c new
GridBagConstraints( 0, 0, 1, 1,
0.0, 0.0, GridBagConstraints.CENTER,
GridBagConstraints.NONE, new
Insets(5, 2, 5, 2), 0, 0) paneeli.add(ken
ttä, c)
  1. Luodaan paneeli.
  2. Asetetaan paneelin asettelijaksi uusi
    GridBagLayout.
  3. Luodaan käyttöliittymä-komponentti.
  4. Luodaan GridBagConstraints-olio, jolle asetetaan
    sopivat attribuuttien arvot.
  5. Lisätään komponentti paneeliin GridBagConstraints
    ia käyttäen.
  6. Palataan tarvittaessa kohtaan 3.

44
GridBagLayout, toinen tapa
JPanel paneeli new JPanel( new
GridBagLayout()) GridBagConstraints c new
GridBagConstraints() JTextField kenttä new
JTextField() c.gridx 0c.gridy 0c.anchor
GridBagConstraints.SOUTHc.insets new
Insets(5, 2, 5, 2) paneeli.add(kenttä,
c) JButton namiska new JButton(pl) c.gridy
1 paneeli.add(namiska, c)
  1. Luodaan paneeli.
  2. Asetetaan paneelin asettelijaksi uusi
    GridBagLayout.
  3. Luodaan GridBagConstraints-olio oletusarvoisilla
    attribuuteilla.
  4. Luodaan käyttöliittymä-komponentti.
  5. Muutetaan GridBag-Constraintsin attribuuttien
    arvoja, mikäli tarpeen.
  6. Lisätään komponentti paneeliin GridBagConstraints
    ia käyttäen.
  7. Palataan tarvittaessa kohtaan 4.

45
Sovellusextends JFrame
public static void main(String args), joka tyypillisesti vain luo kehysluokan ilmentymän luontimetodi
Sovelmaextends JApplet
ei main-metodia, ei (välttämättä) luontimetodiakaan public void init() - selain kutsuu automaattisesti - alustaa esimerkiksi käyttöliittymän lisäksi start(), stop(), destroy()

46
Sovelman ajaminen
appletviewer-ohjelmassa tai selaimessa, selaimien ongelmana sovelmakoodin jääminen välimuistiin (muutokset eivät näy ilman selaimen uudelleenkäynnistystä) Molemmat tarvitsevat HTML-sivun, jolle sovelma sijoitetaan Tulostukset ja virheilmoitukset tulevat joko terminaaliin (appletviewerillä) tai ns. Java-konsoliin (selaimella)
lthtmlgt ltheadgt lttitlegtKolee applettilt/titlegtlt/he
adgt ltbodygt lttable width100 height100
border0gt lttrgt lttd aligncenter
valignmiddlegt ltapplet
codeKoleeAppletti.class width400
height300gt lt/appletgt lt/tdgt
lt/trgt lt/tablegtlt/bodygt lt/htmlgt
47
Appletviewer
Unix-terminaalissa ja Windowsin komentorivillä appletviewer sivuJokaSisaltaaAppletin.html XEmacsissa
48
Java-konsoli(Windowsissa)
49
Sovelma vs. sovellus
  • Sovelmalla kiinteä ikkunan koko, sovelluksella
    joustava
  • Sovelma ei saa kirjoittaa mihinkään tiedostoon,
    sovellus saa
  • ns. servletit (palvelinsovelmat eli palvelmat)
    saavat temmeltää jossain määrin vapaammin
  • Jotkin asiat on tehtävä sovelmissa hieman
    monimutkaisemmin, esimerkkinä kuvan lataaminen
    javax.swing.ImageIcon-olioksi
  • ImageIcon kuva new ImageIcon(mursu.png)
  • ImageIcon kuva null try kuva new
    ImageIcon(this.getImage( new
    java.net.URL(this.getCodeBase(),
    mursu.png))) catch
    (java.net.MalformedURLException e)
    e.printStackTrace()

sovellus sovelma
50
Swing-komponentin piirtäminen
  • Jokainen komponentti vastaa siitä, miten se
    piirretään ruudulle
  • Piirtojärjestelmä vastaa siitä, milloin tämä
    tapahtuu

Piirtojärjestelmä
paintComponent(Graphics g)
komponentti.paint(Graphics g)
paintBorder(Graphics g)
paintChildren(Graphics g)
51
Grafiikkakonteksti
java.awt.Graphics
Mahdollistaa piirtämisen tiettyyn kontekstiin,
esimerkiksi näytöllä olevaan paneeliin tai koneen
muistissa olevaan kuvaan. paintComponent-metodi
saa tällaisen piirtojärjestelmältä
valmiina. Sisältää metodeja, joiden avulla
voidaan piirtää mm. viivoja, ovaaleja,
monikulmioita, tekstiä sekä muistiin ladattuja
kuvia.
java.awt.Graphics2D
Edellisen aliluokka, jossa uusina ominaisuuksina
mm. erityisten kuvio-olioiden piirtäminen sekä
affiinit koordinaatistonmuunnokset. Jokainen
Graphics-olio on yleensä pohjimmiltaan myös
Graphics2D-olio.
52
Piirtäminen
perustuu komponentin omaan
koordinaatistoon
tapahtuu Graphics-luokan metodien avulla
x
(0, 0)
public void paintComponent(Graphics g)
super.paintComponent(g) g.setColor(this.kolee
Väri) g.drawOval(-20, -40, 100, 50)
g.fillRect(80, 35, 20, 200)
g.setColor(this.getForeground())
g.setFont(this.päheeFontti)
g.drawString(hähä, 10, 150)
g.drawImage(this.kuva, 100, 100, null)
hähä
(width-1, height-1)
y
Myös komponentin rajojen ulkopuolelle voi
piirtää, mutta nämä osat eivät näy ruudulla.
53
Kaksoispuskurointi
java.awt.Image
javax.swing.JPanel
Jos komponentti piirretään osissa, piirtämistä ei
kannata tehdä suoraan näytölle, vaan koneen
muistissa näkymättömissä olevaan kuvaan
(bufferiin). Valmis kuva piirretään sitten
ruudulla näkyvään komponenttiin yhtenä
kokonaisuutena, jolloin vältetään kuvan
välkkyminen ja eri osien eriaikainen
piirtyminen. Swing-komponentit ovat kuitenkin
oletusarvoisesti valmiiksi kaksoispuskuroituja.On
siis turvallista piirtää suoraan niihin.
54
Kuvan piirtäminen
g.drawImage(Image img, int x, int y,
ImageObserver obs)
Mitäs laitan koordinaateiksi?
Mikä kumma tää nyt sit on?
Mistä se kuva saadaan?
  • Helpoin tapa
  • Luo ImageIcon-olio haluamastasi kuvatiedostosta.
  • Kysy Image-olio siltä.

Joku, joka odottelee (tarvittaessa) kuvan
latautumista muistiin.
Komponentin sen pisteen, johon haluat sijoittaa
kuvan vasemman yläkulman.
Jos käytät ImageIconia kuvan hakemiseen, tämä
voi hyvin olla null.
Saavat olla myös negatiivisia.
On myös muita, vaikeampia tapoja.
55
Kuvan piirtäminen Graphics2Dllä
g2.drawImage(Image img,
AffineTransform xform, ImageObserver
obs)
Mahdollistaa ns. affiinien muunnosten tekemisen
piirrettävälle kuvalle.Kuvaa voi esimerkiksi
pyöritellä vapaasti. Muunnokset esitetään 3 x 3
-matriisina, java.awt.geom.AffineTransform
. Ohjelmoijan ei kuitenkaan välttämättä tarvitse
juuri vaivata päätään matriisialgebralla
riittää, että tietää mitä haluaa (siirtää,
kääntää, skaalata, vääntää) ja kuinka paljon )
56
Geometriset muunnokset
Siirto (translation)
Viistoutus (shearing)




Kierto (rotation)
Peilaus (mirroring)
Skaalaus (scaling)
57
MVC-arkkitehtuurimalli
MODEL
ohjelman tila visualisoidaan käyttäjälle
käyttäjän toimenpiteet muuttavat ohjelman tilaa
VIEW
CONTROLLER
käyttäjä reagoi näkemäänsä käyttöliittymän
välityksellä
58
Graafinen vuorovaikutteinen peli
ohjelman tila visualisoidaan käyttäjälle
MODEL
käyttäjän toimenpiteet muuttavat ohjelman tilaa
VIEW
CONTROLLER
käyttäjä reagoi näkemäänsä käyttöliittymän
välityksellä
59
VIEW
MODEL
CONTROLLER
Pelimaailman malli paikat, olennot, esineet
Pelimaailman (tai sen tietyn osan) visualisaatio
Muutoksen aiheuttaja, pelimoottori
Kuuntelee pelaajan antamia komentoja ja reagoi
niihin
Piirtää pelin grafiikan(ja toistaa musiikin,
ääni-tehosteet, yms.)
Muistaa kuka missäkin on,mitä tekemässä,
millaisessakunnossa, ja niin edelleen
Pitää yllä pelaajastariippumattomiapelitapahtumi
a
60
Säikeet ja Swing
  • Swingissä on yhden säikeen sääntö
    realisoituneita käyttöliittymäkomponentteja tulee
    käsitellä ainoastaan yhdestä säikeestä, Swingin
    tapahtumankäsittelijäsäikeestä (event dispatching
    thread).
  • Tapahtumankäsittelijäsäie on siis se, joka
    suorittaa kuuntelijoiden sopivien metodien
    kutsumisen vastaavien tapahtumien yhteydessä sekä
    kaikkien Swing-komponenttien piirtämisen
    ruudulle.
  • Realisoitunut tarkoittaa sitä, että komponentti
    on tehty näkyväksi ruudulla. Ylimmän tason
    säiliöille (kuten JFrame) tämän tekee jokin
    metodikutsuista setVisible(true), show() tai
    pack().
  • Alemman tason komponentit realisoituvat, kun ne
    lisätään näkyvään säiliöön tai ne sisältävä
    säiliö tulee näkyväksi.
  • Toisin sanoen vielä näkymättömän käyttöliittymän
    alustus voi periaatteessa tapahtua missä
    säikeessä tahansa, näkyvien komponenttien tilan
    tutkiminen ja muuttaminen sen sijaan vain
    tapahtumankäsittelysäikeessä. Yleensä on
    tyylikkäintä rajata kaikki GUI-toiminta tuon
    säikeen vastuulle. Joskus raskaiden uusien
    käyttöliittymäosakokonaisuuksien alustus voidaan
    kuitenkin tehdä omassa säikeessään, jottei
    tapahtumankäsittely hidastu tarpeettomasti.

61
Entäs sit ku oikeesti tarviin Swingissä muitaki
säikeitä? Vai tarviinks?
  • Case 1 Ajasta riippuvat tapahtumat ja
    javax.swing.Timer
  • Usein haluamme Swing-ohjelmaan myös käyttäjän
    tekemisistä riippumatonta toimintaa, esimerkiksi
    tietyin aikavälein toistuvia tapahtumia.
    Tällaiseen oma säie olisi luonteva ratkaisu,
    mutta hankala, koska se ei saisi käsitellä
    GUI-komponentteja suoraan.
  • Toimiva ratkaisu on käyttää Swingin
    Timer-luokkaa. Se siirtää vastuun ajastetuista
    tapahtumista suoraan tapahtumankäsittelijäsäikeell
    e, joka toteuttaa ne uusina ActionEvent-tapahtumin
    a määrätylle kuuntelijalle. Vähän kuin tapahtuman
    käynnistykseen olisi olemassa oma nappi, jota
    joku kävisi klikkaamassa vaikkapa sekunnin välein.

62
Entäs sit ku oikeesti tarviin Swingissä muitaki
säikeitä? Vai tarviinks?
  • Case 2 Työläissäie ja SwingUtilities.invokeLater(
    )-metodi
  • Raskaita ja aikaavieviä työtehtäviä, kuten
    vaativaa laskentaa tai suurten oliokokonaisuuksien
    alustusta, ei kannata suorittaa
    tapahtumankäsittelysäikeessä, koska tämä näkyisi
    suoraan käyttäjälle vuorovaikutuksen
    hidastumisena. Nämä kannattaa delegoida
    erityisille työläissäikeille, jotka
    rouskuttelevat omaa urakkaansa huomaamattomasti
    taustalla.
  • Usein työläissäikeenkin on tarpeen saada aikaan
    jotakin näkyvää, esimerkiksi ilmoittaa työnsä
    tuloksista käyttöliittymän kautta. Tätä se ei
    kuitenkaan saa tehdä suoraan, vaan työläissäikeen
    pitäisi jotenkin saada vihjattua
    tapahtumankäsittelysäikeelle, että tämän olisi
    aika tehdä jotakin.
  • Ratkaisu tähän kommunikaatio-ongelmaan on
    SwingUtilities-luokan metodi invokeLater(Runnable
    r), joka ottaa parametrinaan jotakin
    suoritettavaa (siis olion, jolla on metodi run())
    ja siirtää sen suoritettavaksi tapahtumankäsittely
    säikeessä myöhemmin, käytännössä hyvinkin pian.
    run()-metodissa on tyypillisesti koodia, joka
    yhdistää työläissäikeen työn tulokset ja
    graafisten käyttöliittymäkomponenttien käsittelyn
    sopivalla tavalla.

63
UML pähkinänkuoressa (Unified Modeling Language)
Olento
- nimi String- elinvoima int- sijainti Karttaruutu
Olento(nimi String, elinvoima int) Olento annaNimi() String annaElinvoima() int muutaElinvoimaa(muutos int) void kuole() void annaSijainti() Karttaruutu asetaSijainti(ruutu Karttaruutu) void teeSiirto() void
Karttaruutu
- nimi String- olennot ListltOlentogt- ruuduntarkkailijat ListltRuuduntarkkailijagt
Karttaruutu(nimi String) Karttaruutu annaNimi() String lisaaOlento(o Olento) boolean poistaOlento(o Olento) boolean sisaltaaOlennon(o Olento) boolean lisaaRuuduntarkkailija(rt Ruuduntarkkailija) void poistaRuuduntarkkailija(rt Ruuduntarkkailija) void
0 .. 1

attribuutit
kaksisuuntainen viittaus olento tuntee
sijaintinsa ja karttaruutu siinä sijaitsevat
olennot olennolla on vain (enintään) yksi
sijainti, mutta karttaruudussa voi olla useita
olentoja
metodit

kursiivi abstrakti luokka tai metodi alleviivaus
staattinen attribuutti tai metodi ISOT_KIRJAIMET
vakioarvo (final)
yksisuuntainen viittaus Karttaruutu-luokan
ilmentymillä saattaa olla attribuuttinaan
viittauksia Ruuduntarkkailijoihin
perintä (extends)
Basiliski
- BASILISKIN_KATSE Pelotteluesine
Basiliski(nimi String) Basiliski teeSiirto() void olentoSaapunut(r Karttaruutu, o Olento) void olentoPoistunut(r Karttaruutu, o Olento) void

- private
protected
public
ltltinterfacegtgtRuuduntarkkailija
olentoSaapunut(r Karttaruutu, o Olento) void olentoPoistunut(r Karttaruutu, o Olento) void
rajapinnan toteuttaminen (implements)
rajapinnan metodit
64
Javadoc-kommentointi
/ Luokka, joka kuvaa maailmaa. Maailma
koostuu kaksiulotteiseen taulukkoon
järjestetyistä Karttaruutu-olioista.
_at_author Veijo Vesisika /public class Maailma
/ Ilmansuunta pohjoinen,
lukuarvoltaan 0. / public static final
int POHJOINEN 0 / Metodi, jonka
avulla voi selvittää tässä maailmassa tietyissä
koordinaateissa sijaitsevan karttaruudun.
_at_param x karttaruudun x-koordinaatti
_at_param y karttaruudun y-koordinaatti
_at_return annetuissa koordinaateissa
sijaitseva karttaruutu tai null,
jos paikassa ei ole karttaruutua
_at_throws PahaPoikkeus jos koordinaatit osoittavat
maailman ulkopuolelle / public
Karttaruutu annaKarttaruutu(int x, int y) throws
PahaPoikkeus ...
65
  • On hyvä tapa Javadoc-kommentoida
  • luokat
  • käyttötarkoitus sanallisesti
  • mahdollisesti myös versionumero (_at_version) ja
    tekijän nimi (_at_author) sekä viittaukset (_at_see)
    muihin luokkiin, joihin on hyvä tutustua tätä
    luokkaa käytettäessä
  • attribuutit (ainakin public- ja
    protected-tyyppiset)
  • käyttötarkoitus sanallisesti
  • metodit (ainakin public- ja protected-tyyppiset)
  • käyttötarkoitus sanallisesti
  • parametrien selitykset (_at_param)
  • kuvaus siitä, mitä metodi voi palauttaa (_at_return)
  • kuvaukset metodin mahdollisesti heittämistä
    poikkeuksista ja niihin johtavista tilanteista
    (_at_throws)

Huomaa pieni mutta tärkeä notaatioero Javadocin
ja muiden useampirivisten kommenttien välillä
/ /
Tämä on Javadocia. Käytä tätä Tämä on
tavallinen kommentti, jollaisia vain sille
varatuissa paikoissa. voi laittaa myös
metodien koodin sekaan. /
/
Javadoc-kommenteista voidaan muodostaa itse
laadituille luokille automaattisesti
vastaavanlaiset dokumentaatiosivut kuin mitä
Java-APIsta löytyy Javan valmiille
luokille. Tämä tapahtuu esimerkiksi komennolla
javadoc -d docs -link http//java.sun.com/j2se/1
.5.0/docs/api/ .java
66
Pakkaukset
  • Pieni Java-projekti kaikki luokat kiltisti
    samassa hakemistossa, ei ongelmaa.
  • Iso Java-projekti luokkien määrän kasvaessa
    kovin suureksi yksi kansio ei enää riitä.
  • Ongelma ihmiselle, ei tietokoneelle. Muista
    ihmisen tiedonkäsittelyn rajat, enintään 42
    hahmotettavaa yksikköä kerrallaan tietoisessa
    tarkastelussa.
  • Luokkakokonaisuus pysyy hallittavana jakamalla se
    osakokonaisuuksiin, pakkauksiin (engl. package).
  • Yhdessä pakkauksessa yhteen asiaan liittyvät
    luokat. Toimintalogiikan malli omassa
    pakkauksessaan, käyttöliittymä omassaan, jne.
    Nämä voidaan puolestaan edelleen jakaa useaan
    erikoistuneeseen pakkaukseen.
  • Käytännössä saman pakkauksen luokat sijoitetaan
    aina samaan hakemistoon.

67
Pakkausten nimeäminen ja nimihierarkiat
  • java.awt.event
  • javax.swing.border
  • org.w3c.dom
  • org.omg.CORBA.portable
  • fi.tkk.inf.studio1.turnaus.labyrintti

virallinen Java (by Sun Microsystems)
järjestöt (W3C, OMG, ...)
Egoboosti- ja brändäysprefiksit. (Huomaa
päinvastainen logiikka kuin www-palvelinten
osoitteissa maa ? organisaatio ? osasto
jne.) Asettavat ohjelmiston suurempaan
kontekstiin, luovat tunnistettavuutta. -
Syventävät (muutenkin jo syvää)
hakemistohierarkiaa.
Robottiturnaussoftan labyrinttien esittämiseen
käytetyt luokat voisivat sijaita tällaisessa
pakkauksessa. Käytännössäkin luokat sijaitsisivat
tuollaisen hakemistopolun päässä,
esimerkiksi C\Javaproggikset\fi\tkk\inf\studio1\
turnaus\labyrintti\Labyrinttiruutu.java
68
Pakkausten käyttö 1
  • Pakkaus, johon luokka sijoittuu, määritellään
  • Avainsanalla package aivan luokan lähdekoodin
    alussa package fi.tkk.inf.studio1.turnaus.lab
    yrintti import java.util.ArrayList
    public class Labyrinttiruutu
  • Tallentamalla luokkatiedosto oikeaan paikkaan
    hakemistohierarkiassa.

Pakkaus rajaa luokkien näkyvyyttä niin, että vain
samaan pakkaukseen kuuluvat luokat nähdään
suoraan muiden pakkausten luokat on
importoitava kuten Javan valmiit luokatkin.
69
Pakkausten käyttö 2
  • Eclipsessä pakkausten käyttö on helppoa ja
    visuaalista.
  • Uusia pakkauksia luodaan samasta valikosta kuin
    uusia luokkiakin. Oletuksena kaikille
    projekteille luodaan oletuspakkaus (default
    package), mutta Eclipse ei arvosta, jos käytät
    sitä.
  • Luokkia voi myöhemmin siirtää pakkauksesta
    toiseen Refactor-valikon Move-toiminnolla. Tämä
    päivittää automaattisesti kaikki viittaukset
    kyseiseen luokkaan ja lisää tarvittavat importit.
  • Komentoriviympäristössä pakkaukset tuovat hieman
    enemmän haastetta. Kääntäminen ja ajaminen
    vaativat nyt ensin ns. classpathin
    määrittelemisen.
  • set CLASSPATHpath1path2path3 (Windows)
  • setenv CLASSPATH path1path2path3 (Unix)
  • Näissä path1 jne. ovat hakemistopolkuja, joista
    (ja joiden alta) luokkia etsitään. Usein riittää
    nykyiseen hakemistoon osoittava polku eli pelkkä
    piste. Se on suhteellinen polku, eli muuttuu
    valitun hakemiston mukaan.
  • Lisäksi luokkia ajaessa täytyy kertoa, mistä
    pakkauksesta (määritellyn classpath-hakemiston
    alta) kyseinen luokka löytyy
  • esim. java fi.tkk.inf.studio1.turnaus.Turnaus

70
Oliopohjaisessa suunnittelussa mietittävää...
  • Käytänkö Javan valmista luokkaa sellaisenaan vai
    kirjoitanko sille aliluokan?
  • Mieti, tarvitseeko luokan ilmentymien osata
    jotain erityistä, jota valmiista luokasta ei
    löydy, vai riittääkö, että luot valmiista
    luokasta olion tietyillä ominaisuuksilla. Usein
    Swingin säiliöille kannattaa laatia omia
    aliluokkia, muille Swing-komponenteille tämä taas
    on harvemmin tarpeen.
  • Korkea koheesio eli (luokkien sisäinen)
    yhtenäisyys GOOD!
  • Yhden luokan vastuut muodostavat selkeän
    kokonaisuuden. Mitään olennaista ei ole
    piilotettu jonnekin muualle, eikä toisaalta
    mukana ole mitään kovin epärelevanttiakaan.
  • Korkea luokkien välinen kytkeytyneisyys BAD!
  • Jokainen luokkien välinen riippuvuussuhde tekee
    kokonaisuudesta vaikeammin hallittavan ja
    muutettavan. Tietysti luokkien välinen yhteistyö
    on välttämätöntä kaikissa vähänkin
    monimutkaisemmissa ohjelmissa, mutta kytkentöjen
    kannattaa olla selkeitä ja niitä kannattaa olla
    mahdollisimman vähän.
  • Harmittomin kytkennän muoto on Swingissä yleensä
    tapahtumankuuntelu luokan A olio rekisteröityy
    tiettyä rajapintaa C edustavana kuuntelijana
    luokan B oliolle ja odottaa, että B ilmoittaa
    Alle uusista tätä kiinnostavista tapahtumista.
  • Kun B joutuu kutsumaan suoraan luokan A metodia,
    kytkentä on vahvempi ja vähemmän joustava.
  • Käyttöliittymä on hyvä pitää erillään
    varsinaisesta sovelluslogiikasta,
    ongelmadomainin mallinnuksesta.

71
Suunnittelumallit(design patterns)
  • Hyväksi havaittuja konsepteja siitä, millainen
    olioyhteisö soveltuu tietynlaisen ongelman
    ratkaisuun. (Kuvailevat yleensä muutamia oliota,
    joilla selkeä vastuunjako. Eivät sinänsä ota
    kantaa siihen, miten olioita kuvaavat luokat
    toteutetaan, eivätkä riipu tietystä
    ohjelmointikielestä.)
  • MVC (Model-View-Controller) sovelluksen
    datamalli, sen esittäminen käyttäjälle sekä
    datamallin muokkaaminen on jaettu eri osien
    vastuulle.
  • Observer yksi olio ilmoittautuu tarkkailemaan
    muutoksia toisen olion tilassa. Tarkkailtava
    (observable) olio ilmoittaa, kun muutoksia
    tapahtuu.
  • Singleton luokka, josta voidaan luoda vain yksi
    olio. Luontimetodi piilotettu, ilmentymän luonti
    (ja luonnin jälkeen tuon ainoan ilmentymän
    hakeminen) tapahtuu jollakin staattisella
    metodilla, kuten getInstance().
  • Factory luokka, jonka metodien avulla voidaan
    luoda usean muun luokan ilmentymiä. Paluuarvon
    tyyppi voi olla jokin rajapinta, jolloin käyttäjä
    voi luoda erilaisia olioita välittämättä niiden
    todellisesta luokasta.
  • Composite suurempi kokonaisuus rakennetaan
    tietynlaisista rakennus-palikkaolioista, jotka
    jälleen voivat edustaa jotakin palikkarajapintaa
    (ja näin ollen olla todelliselta luokaltaan
    hyvin erilaisia keskenään).
  • ja onhan näitä vielä muitakin

72
Tulostusvirrat
perintä
aggregaatio(ohuessa päässä oleva luokka toimii
salmiakkikuviopään luokan rakenteellisena osana)
PrintWriter
OutputStream
Writer
BufferedWriter
OutputStreamWriter
FilterOutputStream
Korkeimman tason virroissa ns. decorator-suunnitte
lumalli. Virrat ovat perusmerkkivirta Writerin
aliluokkia (eli lupaavat saman toiminnallisuuden),
mutta niiden toiminta perustuu johonkin toiseen,
matalamman tason merkkivirta-olioon. Ne lisäävät
sen ympärille uutta toiminnallisuutta,
koristeita. Nämä virrat luodaan siis aina
jonkin olemassa olevan virran pohjalle.
FileWriter
FileOutputStream
tavuvirrat
merkkivirrat
73
Sovelluskehykset(software frameworks)
  • Valmiiden luokkien (ja lopulta pakkausten)
    muodostamia kokonaisuuksia, joiden varaan voi
    rakentaa uusia ohjelmistoja, sekä käyttämällä
    valmiita komponentteja sellaisenaan että
    laatimalla niille tarpeen mukaan omia aliluokkia.
  • Tutuin esimerkki sovelluskehyksestä Swing.
  • Usein sovelluskehysten luokkakokonaisuudet on
    suunniteltu hyvin, ja niissä nähdään monien
    suunnittelumallien soveltamista käytäntöön
  • MVC jokaisen hiemankin monimutkaisemman
    Swing-komponentin perustana nämä kolme osaa.
  • Observer tapahtumankuuntelijat ja kuunneltavat
    komponentit.
  • Singleton tietyt Swing-sovelluksen hallintaan ja
    asetuksiin käytetyt luokat, joilla on aina vain
    yksi ilmentymä.
  • Factory esimerkiksi erilaisten reunusten
    (border) luonti.
  • Composite komponenttien lisääminen säiliöihin
    asettelijoiden avulla.

74
liikenne ______ jono para _____ laku psyki _____
buutti pelottelu _____ ellistäminen runsauden
_____ kuono kusi ___ assistentti
75
liikenne ______ jono para _____ laku psyki _____
buutti pelottelu _____ ellistäminen runsauden
_____ kuono kusi ___ assistentti
Write a Comment
User Comments (0)
About PowerShow.com