informaatioverkostot: studio 1 luentomateriaali

75
1 Informaatioverkostot: Studio 1 Informaatioverkostot: Studio 1 Luentomateriaali Luentomateriaali Janne Käki 2006 MUUTTUJAT TAULUKOT MERKKIJONOT SILMUKAT POLYMORFISMI POIKKEUKSET JAVA-API TIETOVIRRAT SWING SOVELMAT 2D-GRAFIIKKA SÄIKEET JA SWING UML-KAAVIOT JAVADOC PAKKAUKSET SUUNNITTELUSTA 5 1 1 1 7 2 2 8 3 3 3 5 4 0 4 5 5 0 6 3 6 4 6 6

Upload: abe

Post on 21-Jan-2016

35 views

Category:

Documents


0 download

DESCRIPTION

SWING. JAVADOC. UML-KAAVIOT. SÄIKEET JA SWING. 2D-GRAFIIKKA. SOVELMAT. TIETOVIRRAT. JAVA-API. PAKKAUKSET. POLYMORFISMI. SILMUKAT. MERKKIJONOT. TAULUKOT. MUUTTUJAT. SUUNNITTELUSTA. POIKKEUKSET. Informaatioverkostot: Studio 1 Luentomateriaali. 5 11 17 23. 40 45 50 60. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Informaatioverkostot: Studio 1 Luentomateriaali

1

Informaatioverkostot: Studio 1Informaatioverkostot: Studio 1

LuentomateriaaliLuentomateriaaliJanne Käki

2006

MUUTTUJAT

TAULUKOT

MERKKIJONOT

SILMUKAT

POLYMORFISMI

POIKKEUKSET

JAVA-API

TIETOVIRRAT

SWING

SOVELMAT

2D-GRAFIIKKA

SÄIKEET JA SWING

UML-KAAVIOT

JAVADOC

PAKKAUKSET

SUUNNITTELUSTA

5

1

1

1

7

2

3

2

8

3

3

3

5

3

7

4

0

4

5

5

0

6

0

6

3

6

4

6

6

7

0

Page 2: Informaatioverkostot: Studio 1 Luentomateriaali

2

Muutama perusasiaMuutama 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.

Page 3: Informaatioverkostot: Studio 1 Luentomateriaali

3

SijoituslauseSijoituslause

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.)

sijoitu

soperaattori (

ei

yhtäsuuruusmerkki!)

Page 4: Informaatioverkostot: Studio 1 Luentomateriaali

4

Palauttaminen vs. tulostaminenPalauttaminen vs. tulostaminenMetodi, 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”

bööString bööTeksti = palautaBöö();

System.out.println(bööTeksti);

antaa palautettavan arvon käyttöön sille, joka metodia kutsui

tuottaa tekstin näytölle

Page 5: Informaatioverkostot: Studio 1 Luentomateriaali

5

OliokohtaisetOliokohtaiset LuokkakohtaisetLuokkakohtaiset

(static)(static)

Attrib

uu

titA

ttribu

utit

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.

Meto

dit

Meto

dit

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.

Page 6: Informaatioverkostot: Studio 1 Luentomateriaali

6

Tiedon abstraktiotasojaTiedon abstraktiotasoja

bititnollia tai ykkösiä

muistipaikatjoukko bittejä, joilla on yksi osoite

muuttujatnimetty tietyntyyppisen tiedon muistipaikka

oliotnimetty joukko muuttujia (ja operaatioita)

kokoelmatnimetty joukko olioita

Java

n f

oku

s

MUUTTUJAT

Page 7: Informaatioverkostot: Studio 1 Luentomateriaali

7

Erilaisia muuttujiaErilaisia muuttujia

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;

} }

attribuutitmäärittävät olion tilan eli ominaisuuksien arvot

parametritantavat metodille sen suorituksen kannalta tarpeelliset lähtötiedot

apumuuttujatmahdollistavat jonkin arvon muistamisen niin kauan kuin sitä tarvitaan

MUUTTUJAT

Page 8: Informaatioverkostot: Studio 1 Luentomateriaali

8

MuuttujistaMuuttujista• 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ä API:a”;

• Muuttujan arvon lukeminen: käytetään muuttujaa missä tahansa muualla kuin sijoituslauseen vasemmalla puolella.

System.out.println(brutaalimpiSolvaus); if (vihreidenPingviinienLukumaara > 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.

MUUTTUJAT

Page 9: Informaatioverkostot: Studio 1 Luentomateriaali

9

TietotyypeistäTietotyypeistä

alk

eistyyp

it

kokonaisluku

byte

short

int

long

desimaaliluku (liukuluku)float

double

totuusarvo boolean

merkki char

viittau

styypit

merkkijono String

alkeistyyppien kääreet Integer, Double, Boolean, Character, ...

taulukot int[ ], double[ ], Object[ ], Karttaruutu[ ][ ], ...

muut oliotyypit Object, Random, HashSet, Pelotteluesine, ...

olio

ita

MUUTTUJAT

Page 10: Informaatioverkostot: Studio 1 Luentomateriaali

10

Viittaustyyppiset muuttujatViittaustyyppiset 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).

MUUTTUJAT

Page 11: Informaatioverkostot: Studio 1 Luentomateriaali

11

Klassinen for-lauseKlassinen for-lause

for (int i = 0; i < 3; i++) {

...

}

alustus-lause

onkoehtotosi?

suoritettavatlauseet

kasvatus-lause

kyllä

ei

for-lauseen jälkeinen elämä

SILMUKAT

Page 12: Informaatioverkostot: Studio 1 Luentomateriaali

12

for (int i = 0; i < 3; i++) {

...

}

{

int i = 0;

while (i < 3) {

...

i++;

}

}

Tällainen for-lause...

...vastaa while-lauseella toteutettua rakennetta

Mikä merkityson ulommillaaaltosuluilla?

SILMUKAT

Page 13: Informaatioverkostot: Studio 1 Luentomateriaali

13

Iteroiva for-lauseIteroiva for-lause

• 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.

public void tulostaNimet(Set<Olento> olennot) {

for (Olento o : olennot) {

System.out.println(o.annaNimi());

}

}

SILMUKAT

Page 14: Informaatioverkostot: Studio 1 Luentomateriaali

14

public void tulostaNimet(Set<Olento> olennot) { String nimet = ””; for (Olento o : olennot) { nimet += o.annaNimi() + ”, ”; } System.out.println(nimet);}

Arska, Pena, Mats, Rauski,Tulostaa:Miten pääsemme eroon ylimääräisestä pilkusta?

public void tulostaNimet(Set<Olento> olennot) { String nimet = ””; int otuslaskuri = 0; for (Olento o : olennot) { nimet += o.annaNimi(); if (otuslaskuri < olennot.size()-1) { nimet += ”, ”; } otuslaskuri++; } System.out.println(nimet);}

SILMUKAT

Page 15: Informaatioverkostot: Studio 1 Luentomateriaali

15

IteraattoriIteraattori

for (Olio o : kokoelma) {

System.out.println(o);

}

Iterator<Olio> iter = kokoelma.iterator();

while (iter.hasNext()) {

Olio o = iter.next();

System.out.println(o);

}

Vanha tuttu iteroiva for-looppi...

...toimii pinnan alla itse asiassa iteraattoriolion avulla.Sama looppi hieman toisin kirjoitettuna:

Kokoelman on toteutettava rajapintaIterable<T>, joka määrittelee metodinpublic Iterator<T> iterator().

Myös Iterator<T> on itse asiassa rajapinta.Iteraattorin metodi next() palauttaa japoistaa – iteraattorista, ei iteroitavastakokoelmasta – järjestyksessä seuraavanelementin. Metodi hasNext() kertoo,vieläkö elementtejä on jäljellä.

SILMUKAT

Page 16: Informaatioverkostot: Studio 1 Luentomateriaali

16

IteraattoriIteraattori

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.

SILMUKAT

Page 17: Informaatioverkostot: Studio 1 Luentomateriaali

17

TaulukkoTaulukko

0 1 2 3 4 5 6

9 14 2 7 2 0 22int[] taulu = { 9, 14, 2, 7, 2, 0, 22 };

taulu[0] = 1;taulu[2] = 100;taulu[taulu.length-1] = 8;

taulu = new int[5];

0 1 2 3 4 5 6

1 14 100 7 2 0 8

0 1 2 3 4

0 0 0 0 0

Taulukkomuuttujan määrittely ja alustaminen ns. taulukon alustajalla:

Taulukon indeksointi ja sen alkioiden arvojen asettaminen:

Uuden, tyhjän taulukon luonti new-operaattorilla:

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.

TAULUKOT

Page 18: Informaatioverkostot: Studio 1 Luentomateriaali

18

public void kauhistuHirviolaumaa(Olento[] hirviot) {

for (int i = 0; i < hirviot.length; i++) {

hirviot[i].pelottele(this);

}

}

Laskurilla varustettu for-silmukka on kuin luotu taulukon läpikäymiseen, esimerkiksi seuraavassa fiktiivisessä Olento-luokan metodissa:

Muista, ettätaulukon indeksitalkavat nollasta ja

päättyvät yhtäpienempään kuintaulukon koko.

hirviot[i] viittaavuorollaan aina yhteen

taulukon alkioon,siis Olento-tyyppiseenolioon (ellei kyseinen

alkio ole null).

this viittaaaina siihen olioon, jonka

metodista on kyse.Sitä voi käyttää myös

sellaisenaan, esimerkiksiparametrina jollekintoiselle metodille.

TAULUKOT

Page 19: Informaatioverkostot: Studio 1 Luentomateriaali

19

int[] tauluA;

int[] tauluB = null;

int[] tauluC = new int[5];

Pelotteluesine[] tauluD = new Pelotteluesine[1000];

tauluA[0] = 49;

tauluB[0] = 88;

tauluC[5] = 31;

tauluC[2] = 4.86;

tauluA = new double[10];

tauluB = tauluA;

tauluD[666].annaPelottavuus();

Inspired by: http://www.cs.helsinki.fi/u/wikla/Ohjelmointi/Sisalto/3/Taulukot.html#2

Jos määrittelemme seuraavasti

ja sen jälkeen yritämme seuraavia asioita, mikään niistä ei onnistu. Miksi?

Variable tauluA might not have been initialized.java.lang.NullPointerException

java.lang.ArrayIndexOutOfBoundsExceptionPossible loss of precision. Found: double. Required: int.

java.lang.NullPointerException

Variable tauluA might not have been initialized.

Incompatible types. Found: double[ ]. Required: int[ ].

TAULUKOT

Page 20: Informaatioverkostot: Studio 1 Luentomateriaali

20

Kaksiulotteinen taulukkoKaksiulotteinen taulukkoeli taulukoita taulukossaeli taulukoita taulukossa

0

1

2

3

0 1 2 3 4

0 1 2 3 4

0 1 2 3 4

0 1 2 3 4

Olento[][] otusruudukko = new Olento[4][5];

otusruudukko[2][1] = new Olento(”Rauski”, 100);

Luodaan 2D-taulukko eli matriisi, jossa on neljä riviä ja viisi saraketta:

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:

TAULUKOT

Page 21: Informaatioverkostot: Studio 1 Luentomateriaali

21

0

1

2

3

0 1 2 3 4

0 1 2

0

0 1 2 3

Olento[][] otusruudukko = new Olento[4][];

2D-taulukon rivien ei välttämättä tarvitse olla samanpituisia – jokainen alitaulukkohan on yksilöllinen olio, jonka pituus voi olla mitä vain:

otusruudukko[0] = new Olento[5];

otusruudukko[1] = new Olento[3];

otusruudukko[2] = new Olento[1];

otusruudukko[3] = new Olento[4];

otusruudukko[3][3] = new Olento(”Rauski”, 100);

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.

TAULUKOT

Page 22: Informaatioverkostot: Studio 1 Luentomateriaali

22

String[][] ruudut = new String[5][5];

for (int i = 0; i < ruudut.length; i++) {

for (int j = 0; j < ruudut[i].length; j++) {

ruudut[i][j] = i + ”, ” + j;

}

}

for-lauseita voi käyttää myös sisäkkäin.

Kaksiulotteisen taulukon läpikäynnissä tämä on usein tarpeen:

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

TAULUKOT

Page 23: Informaatioverkostot: Studio 1 Luentomateriaali

23

Merkkijonojen vertailuMerkkijonojen 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

trueEsimerkit: Ville Sundberg

MERKKIJONOT

Page 24: Informaatioverkostot: Studio 1 Luentomateriaali

24

EI NÄINEI NÄIN

VAAN VAAN NÄINNÄIN

if (nimi == ”Rauski”) {

if (nimi.equals(”Rauski”)) {

MERKKIJONOT

if (nimi.equalsIgnoreCase(”RAUSKI”)) {TAI JOS TAI JOS KIRJAIN-KIRJAIN-

KOOLLA EI OLE KOOLLA EI OLE MERKITYSTÄMERKITYSTÄ

Page 25: Informaatioverkostot: Studio 1 Luentomateriaali

25

Merkkijonon paloitteluMerkkijonon paloittelu

String lause = ”Kivet on tosi jänniä.”;

String[] sanat = lause.split(” ”);

sanat[0] sanat[1] sanat[2] sanat[3]

”Kivet” ”on” ”tosi” ”jänniä.”

MERKKIJONOT

Page 26: Informaatioverkostot: Studio 1 Luentomateriaali

26

Merkkijonon tulkinta luvuksiMerkkijonon tulkinta luvuksi

Integer.parseInt(String merkkijono)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.parseDouble(String merkkijono) Double-luokan staattinen metodi, muuten sama kuin

yllä mutta tulkitsee merkkijonoja desimaaliluvuiksi (desimaali-erottimena oletusarvoisesti piste)

MERKKIJONOT

Page 27: Informaatioverkostot: Studio 1 Luentomateriaali

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.

MERKKIJONOT

Page 28: Informaatioverkostot: Studio 1 Luentomateriaali

28

Esineprivate String nimi

private double paino

public Esine(String nimi, double paino)

Object

public Object()

Pelotteluesineprivate int pelottavuus

public Pelotteluesine(String nimi,double paino, int pelottavuus)o

min

aisu

uksie

n m

äärä

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() {

...

}

Halutaan luoda uusi Pelotteluesine...

...mutta ennen pelotteluesineen oman pelottavuus-ominaisuuden alustusta on varmistettava, että perustana on oikeaoppinen Esine. Siksi ihan aluksi kutsutaan Esine-luokan luontimetodia...

...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.)

POLYMORFISMI

Kun luodaan uutta Pelotteluesinettä, on sille ensin rakennettava yläluokkien määrittelemä perusta – alustettava ne ominaisuudet, jotka sille kuuluvat 1) Objectina ja 2) Esineenä.

Page 29: Informaatioverkostot: Studio 1 Luentomateriaali

29

Metodin kuormittaminenMetodin kuormittaminen(overloading)(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”);

POLYMORFISMI

Page 30: Informaatioverkostot: Studio 1 Luentomateriaali

30

Metodin korvaaminenMetodin korvaaminen(overriding)(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 @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.

POLYMORFISMI

Page 31: Informaatioverkostot: Studio 1 Luentomateriaali

31

:D

:D

Otus eka = new Otus();

Otus toka = new PäheäOtus();

PäheäOtus kolmas = new PäheäOtus();

toka

kolmas

Metodien staattinen ja Metodien staattinen ja dynaaminen sidontadynaaminen sidonta

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.

POLYMORFISMI

:)

eka

Page 32: Informaatioverkostot: Studio 1 Luentomateriaali

32

RajapinnatRajapinnatRajapinta 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).

Rajapinta 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.

POLYMORFISMI

Page 33: Informaatioverkostot: Studio 1 Luentomateriaali

33

PoikkeuksetPoikkeuksetpublic 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();

}}

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ä”.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.

POIKKEUKSET

Page 34: Informaatioverkostot: Studio 1 Luentomateriaali

34

Erilaisia poikkeusluokkiaErilaisia poikkeusluokkia

Throwable

RuntimeException

Error

ExceptionTarvitsee käsitellä, paitsi...

...näitä ei tarvitse käsitellä.

Ei tarvitse käsitellä.

Kaikkien poikkeus-luokkien yläluokka. (Nimestään huolimatta ei siis rajapinta.)

POIKKEUKSET

Page 35: Informaatioverkostot: Studio 1 Luentomateriaali

35

Keskeisimmät Java-API:n pakkauksetKeskeisimmät Java-API:n pakkauksetAPI = 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

JAVA-API

Page 36: Informaatioverkostot: Studio 1 Luentomateriaali

36

Luetaan sitä API:a!Luetaan sitä API:a!Mutta miten?Mutta miten?

1. Etsi API:sta oikea luokka haluamasi asian tekemiseen.2. Etsi luokasta metodi, jolla sen saa tekemään tuon asian.3. Selvitä, miten kyseistä metodia käytetään.

Java-ohjelmoinnissa monien ongelmien ratkaisu käy seuraavaan tapaan:

• 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ä. :)

API:n lukemisessa on kuitenkin muutama sudenkuoppa, joita kannattaa varoa:

JAVA-API

Page 37: Informaatioverkostot: Studio 1 Luentomateriaali

37

TietovirratTietovirrat

Tavuvirta Merkkivirta

SyöttöSyöttö

(input)(input)java.io.java.io.

InputStreamInputStream java.io.Readerjava.io.Reader

TulostusTulostus

(output)(output)java.io.java.io.

OutputStreamOutputStream java.io.Writerjava.io.Writer

TIETOVIRRAT

Page 38: Informaatioverkostot: Studio 1 Luentomateriaali

38

Näppäimistön lukeminenNäppäimistön lukeminen

InputStream(System.in)

InputStreamReader

BufferedReader

näppäim

istö

01001110

br

11101011

öm

mene avantoon

katso olentoa 4

tavut

merkit

merkkijonot

TIETOVIRRAT

Page 39: Informaatioverkostot: Studio 1 Luentomateriaali

39

BufferedReader lukija = new BufferedReader( new InputStreamReader(System.in));

IOException (tietovirtahepo) vaanii kaikissa tietovirroissa

InputStream(System.in)

InputStreamReader

BufferedReader

TIETOVIRRAT

Page 40: Informaatioverkostot: Studio 1 Luentomateriaali

40

Graafisen Java-ohjelman osatGraafisen Java-ohjelman osat

näkyvät osat näkymättömät osat

Komponentit Säiliöt AsettelijatTapahtumat

ja kuuntelijatMuut

apuluokat

pakkaus javax.swing javax.swing java.awtjava.awt.eventjavax.swing.event

java.awtjavax.swing.border

tärkeitäesimerkki-

luokkia

JButtonJLabelJTextFieldJMenuItemJComboBox... ja monta muuta

JFrameJAppletJDialog

JPanelJScrollPaneJSplitPane

FlowLayoutBorderLayoutGridBagLayoutGridLayoutBoxLayoutCardLayout

ActionEventActionListenerMouseEventMouseListenerChangeEventChangeListener... ja monia muita

ColorDimensionFontGridBagConstraintsInsetsBorder (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

SWING

Page 41: Informaatioverkostot: Studio 1 Luentomateriaali

41

Tapahtumapohjainen Tapahtumapohjainen ohjelmointiohjelmointi

Tapahtuman-Tapahtuman-käsittelysäiekäsittelysäie

(event (event dispatching dispatching

thread)thread)

käyttöliittymäkäyttöliittymän alustusn alustus

tapahtuman tapahtuman odottelu…odottelu…

ohjelman ohjelman käynnistykäynnistyss

TapahtumTapahtumaa

käyttäjä tekee käyttäjä tekee jotain…jotain…

Tapahtuman Tapahtuman kuuntelija(t)kuuntelija(t)

tapahtumaantapahtumaanreagointireagointi(”ohjelma(”ohjelma

tekee jotain”)tekee jotain”)

ohjelman ohjelman sulkeminesulkeminenn

TyöläissäiTyöläissäiee

(worker (worker thread)thread)

SWING

Page 42: Informaatioverkostot: Studio 1 Luentomateriaali

42

GridBagConstraintsGridBagConstraints

GridBagConstraints c =GridBagConstraints c =

new GridBagConstraints( new GridBagConstraints(

0, 0, 0, 0,

1, 1, 1, 1,

0.0, 0.0, 0.0, 0.0,

GridBagConstraints.CENTER, GridBagConstraints.CENTER,

GridBagConstraints.BOTH, GridBagConstraints.BOTH,

new Insets(5, 2, 5, 2), new Insets(5, 2, 5, 2),

0, 0); 0, 0);

gridx ja gridy:komponentin sijainti-koordinaatit ”gridissä”(vasemmalta ylhäältä luettuna)

gridwidth ja gridheight:komponentin leveys ja korkeus(riveissä ja sarakkeissa)

weightx ja weighty:komponentin suhteellinenpainoarvo (0.0–1.0)säiliötä täytettäessä

anchor:komponentin sijainti solunsisällä (CENTER, NORTH,EAST, SOUTHWEST, jne.)

fill:kuinka komponentti täyttääsolunsa (HORIZONTAL,VERTICAL, BOTH tai NONE)

insets:montako pikseliätyhjää tilaakomponentinympärille jätetään(ylös, vasemmalle,alas, oikealle)

ipadx ja ipady:paljonko tyhjää reunusta(”paddingia”) kompo-nentin sisään jätetäänsen minimikoossa

SWING

Page 43: Informaatioverkostot: Studio 1 Luentomateriaali

43

GridBagLayoutGridBagLayout

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.

JPanel paneeli = new JPanel(JPanel paneeli = new JPanel( new GridBagLayout()); new GridBagLayout());

JTextField kenttä = new JTextField();JTextField kenttä = new JTextField();

GridBagConstraints c =GridBagConstraints c = new GridBagConstraints( new GridBagConstraints( 0, 0, 0, 0, 1, 1, 1, 1, 0.0, 0.0, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.CENTER, GridBagConstraints.NONE, GridBagConstraints.NONE, new Insets(5, 2, 5, 2), new Insets(5, 2, 5, 2), 0, 0); 0, 0);

paneeli.add(kenttä, c);paneeli.add(kenttä, c);

SWING

Page 44: Informaatioverkostot: Studio 1 Luentomateriaali

44

GridBagLayout, toinen tapaGridBagLayout, toinen tapa

1. Luodaan paneeli.

2. Asetetaan paneelin asettelijaksi uusi GridBagLayout.

3. Luodaan GridBagConstraints-olio oletusarvoisilla attribuuteilla.

4. Luodaan käyttöliittymä-komponentti.

5. Muutetaan GridBag-Constraints:in attribuuttien arvoja, mikäli tarpeen.

6. Lisätään komponentti paneeliin GridBagConstraints:ia käyttäen.

7. Palataan tarvittaessa kohtaan 4.

JPanel paneeli = new JPanel(JPanel paneeli = new JPanel( new GridBagLayout()); new GridBagLayout());

GridBagConstraints c =GridBagConstraints c = new GridBagConstraints(); new GridBagConstraints();

JTextField kenttä = new JTextField();JTextField kenttä = new JTextField();

c.gridx = 0;c.gridx = 0;c.gridy = 0;c.gridy = 0;c.anchor = GridBagConstraints.SOUTH;c.anchor = GridBagConstraints.SOUTH;c.insets = new Insets(5, 2, 5, 2);c.insets = new Insets(5, 2, 5, 2);

paneeli.add(kenttä, c);paneeli.add(kenttä, c);

JButton namiska = new JButton(”pl”);JButton namiska = new JButton(”pl”);

c.gridy = 1;c.gridy = 1;

paneeli.add(namiska, c);paneeli.add(namiska, c);

SWING

Page 45: Informaatioverkostot: Studio 1 Luentomateriaali

45

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()

Sovellusextends JFrame

• public static void main(String[] args), joka tyypillisesti vain luo kehysluokan ilmentymän• luontimetodi

SOVELMAT

Page 46: Informaatioverkostot: Studio 1 Luentomateriaali

46

Sovelman ajaminenSovelman ajaminen

<html><html>

<head><head> <title>Kolee appletti</title> <title>Kolee appletti</title></head></head>

<body><body> <table width=”100%” height=”100%” border=”0”> <table width=”100%” height=”100%” border=”0”> <tr> <tr> <td align=”center” valign=”middle”> <td align=”center” valign=”middle”>

<applet code=”KoleeAppletti.class” width=”400” height=”300”><applet code=”KoleeAppletti.class” width=”400” height=”300”> </applet> </applet>

</td></td> </tr> </tr> </table> </table></body></body>

</html></html>

• 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)

SOVELMAT

Page 47: Informaatioverkostot: Studio 1 Luentomateriaali

47

AppletviewerAppletviewer

• Unix-terminaalissa ja Windowsin komentorivillä:

appletviewer sivuJokaSisaltaaAppletin.html

• XEmacsissa:

SOVELMAT

Page 48: Informaatioverkostot: Studio 1 Luentomateriaali

48

Java-konsoliJava-konsoli(Windowsissa)(Windowsissa)

SOVELMAT

Page 49: Informaatioverkostot: Studio 1 Luentomateriaali

49

Sovelma vs. sovellusSovelma 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

SOVELMAT

Page 50: Informaatioverkostot: Studio 1 Luentomateriaali

50

Swing-komponentin piirtäminenSwing-komponentin piirtäminen

komponentti.paint(Graphics g)komponentti.paint(Graphics g)

paintComponent(Graphics g)paintComponent(Graphics g)

paintBorder(Graphics g)paintBorder(Graphics g)

paintChildren(Graphics g)paintChildren(Graphics g)

PiirtojärjestelmäPiirtojärjestelmä

komponentti.repaint()komponentti.repaint()

korvaa tämä tarvittaessa korvaa tämä tarvittaessa omalla toteutuksellaomalla toteutuksella

kutsu tätä tarvittaessakutsu tätä tarvittaessa

• Jokainen komponentti vastaa siitä, Jokainen komponentti vastaa siitä, mitenmiten se piirretään se piirretään ruudulleruudulle

• Piirtojärjestelmä vastaa siitä, Piirtojärjestelmä vastaa siitä, milloinmilloin tämä tapahtuu tämä tapahtuu

2D-GRAFIIKKA

Page 51: Informaatioverkostot: Studio 1 Luentomateriaali

51

GrafiikkakontekstiGrafiikkakonteksti

java.awt.Graphicsjava.awt.Graphics

java.awt.Graphics2Djava.awt.Graphics2D

Mahdollistaa piirtämisen tiettyyn kontekstiin, esimerkiksi Mahdollistaa piirtämisen tiettyyn kontekstiin, esimerkiksi näytöllä olevaan paneeliin tai koneen muistissa olevaan kuvaan.näytöllä olevaan paneeliin tai koneen muistissa olevaan kuvaan.

paintComponentpaintComponent-metodi saa tällaisen piirtojärjestelmältä -metodi saa tällaisen piirtojärjestelmältä valmiina.valmiina.

Sisältää metodeja, joiden avulla voidaan piirtää mm. viivoja, Sisältää metodeja, joiden avulla voidaan piirtää mm. viivoja, ovaaleja, monikulmioita, tekstiä sekä muistiin ladattuja kuvia.ovaaleja, monikulmioita, tekstiä sekä muistiin ladattuja kuvia.

Edellisen aliluokka, jossa uusina ominaisuuksina mm. erityisten Edellisen aliluokka, jossa uusina ominaisuuksina mm. erityisten kuvio-olioiden piirtäminen sekä affiinit kuvio-olioiden piirtäminen sekä affiinit koordinaatistonmuunnokset.koordinaatistonmuunnokset.

Jokainen Jokainen GraphicsGraphics-olio on yleensä pohjimmiltaan myös -olio on yleensä pohjimmiltaan myös Graphics2DGraphics2D-olio.-olio.

2D-GRAFIIKKA

Page 52: Informaatioverkostot: Studio 1 Luentomateriaali

52

Piirtäminen…Piirtäminen…

xx

yy(width-1, (width-1, height-1)height-1)

… … perustuu komponentinperustuu komponentin omaan koordinaatistoon: omaan koordinaatistoon:

Myös komponentin rajojen Myös komponentin rajojen ulkopuolelle voi ”piirtää”, mutta ulkopuolelle voi ”piirtää”, mutta nämä osat eivät näy ruudulla.nämä osat eivät näy ruudulla.

… … tapahtuu tapahtuu GraphicsGraphics-luokan-luokan metodien avulla: metodien avulla:

public void paintComponent(Graphics g) {public void paintComponent(Graphics g) {

super.paintComponent(g);super.paintComponent(g);

g.setColor(this.koleeVäri);g.setColor(this.koleeVäri); g.drawOval(-20, -40, 100, 50); g.drawOval(-20, -40, 100, 50);

g.fillRect(80, 35, 20, 200);g.fillRect(80, 35, 20, 200);

g.setColor(this.getForeground());g.setColor(this.getForeground()); g.setFont(this.päheeFontti); g.setFont(this.päheeFontti); g.drawString(”hähä”, 10, 150); g.drawString(”hähä”, 10, 150);

g.drawImage(this.kuva, 100, 100, null);g.drawImage(this.kuva, 100, 100, null);

}}

(0, 0)(0, 0)

hähähähä

2D-GRAFIIKKA

Page 53: Informaatioverkostot: Studio 1 Luentomateriaali

53

KaksoispuskurointiKaksoispuskurointi

Jos komponentti piirretään osissa, piirtämistä ei kannata tehdä suoraan Jos komponentti piirretään osissa, piirtämistä ei kannata tehdä suoraan näytölle, vaan koneen muistissa näkymättömissä olevaan kuvaan näytölle, vaan koneen muistissa näkymättömissä olevaan kuvaan (“bufferiin”). Valmis kuva piirretään sitten ruudulla näkyvään (“bufferiin”). Valmis kuva piirretään sitten ruudulla näkyvään komponenttiin yhtenä kokonaisuutena, jolloin vältetään kuvan välkkyminen komponenttiin yhtenä kokonaisuutena, jolloin vältetään kuvan välkkyminen ja eri osien eriaikainen piirtyminen.ja eri osien eriaikainen piirtyminen.

Swing-komponentit ovat kuitenkin oletusarvoisesti valmiiksi Swing-komponentit ovat kuitenkin oletusarvoisesti valmiiksi kaksoispuskuroitujakaksoispuskuroituja..On siis turvallista piirtää suoraan niihin.On siis turvallista piirtää suoraan niihin.

java.awt.Imagejava.awt.Imagejavax.swing.JPaneljavax.swing.JPanel

2D-GRAFIIKKA

Page 54: Informaatioverkostot: Studio 1 Luentomateriaali

54

Kuvan piirtäminenKuvan piirtäminen

g.drawImage(Image img, int x, int y, ImageObserver obs);g.drawImage(Image img, int x, int y, ImageObserver obs);

Mistä se kuva Mistä se kuva saadaan?saadaan?

Mitäs laitan Mitäs laitan koordinaateiksi?koordinaateiksi?

Mikä kumma tää Mikä kumma tää nyt sit on?nyt sit on?

Helpoin tapa:Helpoin tapa:

1.1. Luo Luo ImageIconImageIcon-olio -olio haluamastasi haluamastasi kuvatiedostosta.kuvatiedostosta.

2.2. Kysy Kysy ImageImage-olio -olio siltä.siltä.

On myös muita, On myös muita, vaikeampia vaikeampia tapoja.tapoja.

Joku, joka odottelee Joku, joka odottelee (tarvittaessa) kuvan (tarvittaessa) kuvan latautumista latautumista muistiin.muistiin.

Jos käytät Jos käytät ImageIconImageIcon:ia :ia kuvan hakemiseen, kuvan hakemiseen, tämä voi hyvin olla tämä voi hyvin olla nullnull..

Komponentin sen Komponentin sen pisteen, johon pisteen, johon haluat sijoittaa haluat sijoittaa kuvan vasemman kuvan vasemman yläkulman.yläkulman.

Saavat olla myös Saavat olla myös negatiivisia.negatiivisia.

2D-GRAFIIKKA

Page 55: Informaatioverkostot: Studio 1 Luentomateriaali

55

Kuvan piirtäminen Kuvan piirtäminen Graphics2DGraphics2D:llä:llä

g2.drawImage(Image img,g2.drawImage(Image img, AffineTransform xform, AffineTransform xform, ImageObserver obs); ImageObserver obs);

Mahdollistaa ns. affiinien muunnosten tekemisen piirrettävälle Mahdollistaa ns. affiinien muunnosten tekemisen piirrettävälle kuvalle.kuvalle.Kuvaa voi esimerkiksi pyöritellä vapaasti.Kuvaa voi esimerkiksi pyöritellä vapaasti.

Muunnokset esitetään 3 x 3 -matriisina, Muunnokset esitetään 3 x 3 -matriisina, java.awt.geom.AffineTransformjava.awt.geom.AffineTransform ..

Ohjelmoijan ei kuitenkaan välttämättä tarvitse juuri vaivata Ohjelmoijan ei kuitenkaan välttämättä tarvitse juuri vaivata päätään matriisialgebralla – riittää, että tietää mitä haluaa (siirtää, päätään matriisialgebralla – riittää, että tietää mitä haluaa (siirtää, kääntää, skaalata, vääntää) ja kuinka paljon :)kääntää, skaalata, vääntää) ja kuinka paljon :)

2D-GRAFIIKKA

Page 56: Informaatioverkostot: Studio 1 Luentomateriaali

56

Geometriset muunnoksetGeometriset muunnokset

Siirto (translation)Siirto (translation)

Kierto (rotation)Kierto (rotation)

Viistoutus (shearing)Viistoutus (shearing)

Skaalaus (scaling)Skaalaus (scaling)

Peilaus (mirroring)Peilaus (mirroring)

2D-GRAFIIKKA

Page 57: Informaatioverkostot: Studio 1 Luentomateriaali

57

MVC-arkkitehtuurimalliMVC-arkkitehtuurimalli

MODELMODEL

VIEWVIEW

CONTROLLERCONTROLLER

käyttäjän toimenpiteet käyttäjän toimenpiteet muuttavat ohjelman tilaamuuttavat ohjelman tilaa

ohjelman tila ohjelman tila visualisoidaan visualisoidaan

käyttäjällekäyttäjälle

käyttäjä reagoi näkemäänsä käyttäjä reagoi näkemäänsä käyttöliittymän välitykselläkäyttöliittymän välityksellä

2D-GRAFIIKKA

Page 58: Informaatioverkostot: Studio 1 Luentomateriaali

58

Graafinen vuorovaikutteinen peliGraafinen vuorovaikutteinen peli

dsfadsfa

xx

yy

VIEWVIEW

MODELMODEL

CONTROLLERCONTROLLER

käyttäjän toimenpiteet käyttäjän toimenpiteet muuttavat ohjelman tilaamuuttavat ohjelman tilaa

ohjelman tila ohjelman tila visualisoidaan visualisoidaan

käyttäjällekäyttäjälle

käyttäjä reagoi näkemäänsä käyttäjä reagoi näkemäänsä käyttöliittymän välitykselläkäyttöliittymän välityksellä

2D-GRAFIIKKA

Page 59: Informaatioverkostot: Studio 1 Luentomateriaali

59

dsfadsfa

xx

yy

Pelimaailman malli: Pelimaailman malli: paikat, olennot, paikat, olennot, esineetesineet

VIEWVIEWMODELMODEL CONTROLLERCONTROLLER

Pelimaailman (tai sen Pelimaailman (tai sen tietyn osan) tietyn osan) visualisaatiovisualisaatio

Muutoksen Muutoksen aiheuttaja, aiheuttaja, ”pelimoottori””pelimoottori”

Kuuntelee pelaajanKuuntelee pelaajanantamia komentoja jaantamia komentoja ja

reagoi niihinreagoi niihinPiirtää pelin grafiikanPiirtää pelin grafiikan(ja toistaa musiikin, ääni-(ja toistaa musiikin, ääni-

tehosteet, yms.)tehosteet, yms.)

Muistaa kuka missäkin on,Muistaa kuka missäkin on,mitä tekemässä, millaisessamitä tekemässä, millaisessakunnossa, ja niin edelleenkunnossa, ja niin edelleen

Pitää yllä pelaajastaPitää yllä pelaajastariippumattomiariippumattomiapelitapahtumiapelitapahtumia

2D-GRAFIIKKA

Page 60: Informaatioverkostot: Studio 1 Luentomateriaali

60

Säikeet ja SwingSä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.

SÄIKEET JA SWING

Page 61: Informaatioverkostot: Studio 1 Luentomateriaali

61

Entäs sit ku oikeesti tarviin Entäs sit ku oikeesti tarviin Swingissä muitaki säikeitä? Vai Swingissä muitaki säikeitä? Vai

tarviinks?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äikeelle, joka toteuttaa ne uusina ActionEvent-tapahtumina määrätylle kuuntelijalle. Vähän kuin tapahtuman käynnistykseen olisi olemassa oma nappi, jota joku kävisi klikkaamassa vaikkapa sekunnin välein.

SÄIKEET JA SWING

Page 62: Informaatioverkostot: Studio 1 Luentomateriaali

62

Entäs sit ku oikeesti tarviin Entäs sit ku oikeesti tarviin Swingissä muitaki säikeitä? Vai Swingissä muitaki säikeitä? Vai

tarviinks?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äsittelysä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.

SÄIKEET JA SWING

Page 63: Informaatioverkostot: Studio 1 Luentomateriaali

63

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

Basiliski

- BASILISKIN_KATSE : Pelotteluesine

+ Basiliski(nimi : String) : Basiliski+ teeSiirto() : void+ olentoSaapunut(r : Karttaruutu, o : Olento) : void+ olentoPoistunut(r : Karttaruutu, o : Olento) : void

<<interface>>Ruuduntarkkailija

+ olentoSaapunut(r : Karttaruutu, o : Olento) : void+ olentoPoistunut(r : Karttaruutu, o : Olento) : void

UML pähkinänkuoressaUML pähkinänkuoressa (Unified Modeling Language)(Unified Modeling Language)

Karttaruutu- nimi : String- olennot : List<Olento>- ruuduntarkkailijat : List<Ruuduntarkkailija>

+ 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

perintä (extends)

rajapinnan toteuttaminen (implements)

yksisuuntainen viittaus: Karttaruutu-luokan ilmentymillä saattaa olla attribuuttinaan viittauksia Ruuduntarkkailijoihin

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

* 0 .. 1

*

*

kursiivi: abstrakti luokka tai metodi

alleviivaus: staattinen attribuutti tai metodi

ISOT_KIRJAIMET: vakioarvo (final)

- private

# protected

+ public

attribuutit

metodit

rajapinnan metodit

UML-KAAVIOT

Page 64: Informaatioverkostot: Studio 1 Luentomateriaali

64

Javadoc-kommentointiJavadoc-kommentointi/** * Luokka, joka kuvaa maailmaa. Maailma koostuu kaksiulotteiseen taulukkoon * järjestetyistä Karttaruutu-olioista. * * @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. * * @param x karttaruudun x-koordinaatti * @param y karttaruudun y-koordinaatti * * @return annetuissa koordinaateissa sijaitseva karttaruutu tai null, * jos paikassa ei ole karttaruutua * * @throws PahaPoikkeus jos koordinaatit osoittavat maailman ulkopuolelle */ public Karttaruutu annaKarttaruutu(int x, int y) throws PahaPoikkeus {

...

}

JAVADOC

Page 65: Informaatioverkostot: Studio 1 Luentomateriaali

65

On hyvä tapa Javadoc-kommentoida:• luokat

käyttötarkoitus sanallisesti mahdollisesti myös versionumero (@version) ja tekijän nimi (@author) sekä viittaukset

(@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 (@param) kuvaus siitä, mitä metodi voi palauttaa (@return) kuvaukset metodin mahdollisesti heittämistä poikkeuksista ja niihin johtavista tilanteista

(@throws)

Javadoc-kommenteista voidaan muodostaa itse laadituille luokille automaattisesti vastaavanlaiset dokumentaatiosivut kuin mitä Java-API:sta 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

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

Page 66: Informaatioverkostot: Studio 1 Luentomateriaali

66

PakkauksetPakkaukset 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 4±2 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.

PAKKAUKSET

Page 67: Informaatioverkostot: Studio 1 Luentomateriaali

67

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.

Pakkausten nimeäminen ja Pakkausten nimeäminen ja nimihierarkiatnimihierarkiat

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, ...)

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

PAKKAUKSET

Page 68: Informaatioverkostot: Studio 1 Luentomateriaali

68

Pakkausten käyttö 1Pakkausten käyttö 1

Pakkaus, johon luokka sijoittuu, määritellään:

1. Avainsanalla package aivan luokan lähdekoodin alussa:

package fi.tkk.inf.studio1.turnaus.labyrintti;

import java.util.ArrayList;

public class Labyrinttiruutu {

2. 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.

PAKKAUKSET

Page 69: Informaatioverkostot: Studio 1 Luentomateriaali

69

Pakkausten käyttö 2Pakkausten 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 CLASSPATH=path1;path2;path3 (Windows) setenv CLASSPATH path1:path2:path3 (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 &

PAKKAUKSET

Page 70: Informaatioverkostot: Studio 1 Luentomateriaali

70

Oliopohjaisessa suunnittelussa Oliopohjaisessa suunnittelussa mietittävää...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 A:lle 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”.

SUUNNITTELUSTA

Page 71: Informaatioverkostot: Studio 1 Luentomateriaali

71

SuunnittelumallitSuunnittelumallit(design patterns)(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

SUUNNITTELUSTA

Page 72: Informaatioverkostot: Studio 1 Luentomateriaali

72

TulostusvirratTulostusvirrat

OutputStream

OutputStreamWriter

Writer

BufferedWriter

PrintWriter

FileWriter

FilterOutputStream

FileOutputStream

perintä

aggregaatio(ohuessa päässä oleva luokka toimii salmiakkikuviopään luokan rakenteellisena osana)

tavuvirrat merkkivirrat

Korkeimman tason virroissa ns. decorator-suunnittelumalli. 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.

SUUNNITTELUSTA

Page 73: Informaatioverkostot: Studio 1 Luentomateriaali

73

SovelluskehyksetSovelluskehykset(software frameworks)(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.

SUUNNITTELUSTA

Page 74: Informaatioverkostot: Studio 1 Luentomateriaali

74

liikenne ______ jono

para _____ laku

psyki _____ buutti

pelottelu _____ ellistäminen

runsauden _____ kuono

kusi ___ assistentti

Page 75: Informaatioverkostot: Studio 1 Luentomateriaali

75

liikenne ______ jono

para _____ laku

psyki _____ buutti

pelottelu _____ ellistäminen

runsauden _____ kuono

kusi ___ assistentti

MERKKI

METRI

ATRI

MOGARI

ESINE

SARVI

TUNTI