Ohjelmoinnin peruskurssien laaja oppimäärä

Samankaltaiset tiedostot
Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Rajapinnat ja sisäluokat

Luento 2. T Ohjelmoinnin jatkokurssi T1 & T Ohjelmoinnin jatkokurssi L1. Luennoitsija: Otto Seppälä

Java kahdessa tunnissa. Jyry Suvilehto

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Taulukot & Periytyminen

Ohjelmoinnin jatkokurssi, kurssikoe

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

Java-kielen perusteet

Olio-ohjelmointi Javalla

Ohjelmoinnin peruskurssien laaja oppimäärä

Vertailulauseet. Ehtolausekkeet. Vertailulauseet. Vertailulauseet. if-lauseke. if-lauseke. Javan perusteet 2004

Ohjelmoinnin peruskurssien laaja oppimäärä

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

Sisällys. JAVA-OHJELMOINTI Osa 7: Abstrakti luokka ja rajapinta. Abstraktin luokan idea. Abstrakti luokka ja metodi. Esimerkki

16. Javan omat luokat 16.1

812341A Olio-ohjelmointi Peruskäsitteet jatkoa

Rajapinta (interface)

Luokka Murtoluku uudelleen. Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista.

1. Omat operaatiot 1.1

14. Poikkeukset 14.1

9. Periytyminen Javassa 9.1

Java-kielen perusteet

15. Ohjelmoinnin tekniikkaa 15.1

Luento 4. T Ohjelmoinnin jatkokurssi T1 & T Ohjelmoinnin jatkokurssi L1. Luennoitsija: Otto Seppälä

Sisällys. 1. Omat operaatiot. Yleistä operaatioista. Yleistä operaatioista

Mikä yhteyssuhde on?

Listarakenne (ArrayList-luokka)

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Olion elinikä. Olion luominen. Olion tuhoutuminen. Olion tuhoutuminen. Kissa rontti = null; rontti = new Kissa();

Sisältö. 22. Taulukot. Yleistä. Yleistä

15. Ohjelmoinnin tekniikkaa 15.1

Metodien tekeminen Javalla

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma.

Kompositio. Mikä komposition on? Kompositio vs. yhteyssuhde Kompositio Javalla Konstruktorit set-ja get-metodit tostring-metodi Pääohjelma

14. Poikkeukset 14.1

Sisällys. JAVA-OHJELMOINTI Osa 6: Periytyminen ja näkyvyys. Luokkahierarkia. Periytyminen (inheritance)

Metodit. Metodien määrittely. Metodin parametrit ja paluuarvo. Metodien suorittaminen eli kutsuminen. Metodien kuormittaminen

Sisältö. 2. Taulukot. Yleistä. Yleistä

7. Näytölle tulostaminen 7.1

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Poikkeukset ja tietovirrat: Virhetilanteiden ja syötevirtojen käsittely

11. Javan valintarakenteet 11.1

Javan perusteita. Janne Käki

Informaatioteknologian laitos Olio-ohjelmoinnin perusteet / Salo

7. Oliot ja viitteet 7.1

Rajapinnasta ei voida muodostaa olioita. Voidaan käyttää tunnuksen tyyppinä. Rajapinta on kuitenkin abstraktia luokkaa selvästi abstraktimpi tyyppi.

TIETORAKENTEET JA ALGORITMIT

9. Periytyminen Javassa 9.1

Tietueet. Tietueiden määrittely

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 16.3

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmointi 2 / 2010 Välikoe / 26.3

Java-kielen perusteita

on ohjelmoijan itse tekemä tietotyyppi, joka kuvaa käsitettä

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen

Ohjelmoinnin peruskurssien laaja oppimäärä

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 15.3

Ohjelmoinnin peruskurssien laaja oppimäärä

Rinnakkaisohjelmointi kurssi. Opintopiiri työskentelyn raportti

5/20: Algoritmirakenteita III

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

Sisällys. 11. Rajapinnat. Johdanto. Johdanto

Tehtävä 1. Tehtävä 2. Arvosteluperusteet Koherentti selitys Koherentti esimerkki

A) on käytännöllinen ohjelmointitekniikka. = laajennetaan aikaisemmin tehtyjä luokkia (uudelleenkäytettävyys)

Sisällys. 6. Metodit. Oliot viestivät metodeja kutsuen. Oliot viestivät metodeja kutsuen

Ohjelmoinnin peruskurssien laaja oppimäärä

Sisällys. 15. Lohkot. Lohkot. Lohkot

Groovy. Niko Jäntti Jesper Haapalinna Group 31

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Pakkaukset ja määreet

Ohjelmoinnin perusteet Y Python

Sisällys. 9. Periytyminen Javassa. Periytymismekanismi Java-kielessä. Periytymismekanismi Java-kielessä

Sisällys. Metodien kuormittaminen. Luokkametodit ja -attribuutit. Rakentajat. Metodien ja muun luokan sisällön järjestäminen. 6.2

13. Loogiset operaatiot 13.1

A TIETORAKENTEET JA ALGORITMIT

Lyhyt kertaus osoittimista

Tietorakenteet. JAVA-OHJELMOINTI Osa 5: Tietorakenteita. Sisällys. Merkkijonot (String) Luokka String. Metodeja (public)

Sisältö. Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 6.2

Metodit Arvotyyppi. Metodit Arvotyyppi. Metodit Parametrit. Metodit Parametrit. Metodit Kuormittaminen. Metodit Kuormittaminen. Javan perusteet

11. Javan valintarakenteet 11.1

Java-API, rajapinnat, poikkeukset, UML,...

Ohjelmoinnin peruskurssien laaja oppimäärä

7/20: Paketti kasassa ensimmäistä kertaa

12. Javan toistorakenteet 12.1

11. Javan toistorakenteet 11.1

Ohjelmoinnin peruskurssien laaja oppimäärä

Sisällys. 9. Periytyminen Javassa. Periytymismekanismi Java-kielessä. Periytymismekanismi Java-kielessä

Ohjelmoinnin peruskurssien laaja oppimäärä

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. X Poikkeusten käsittelystä

12. Javan toistorakenteet 12.1

T Henkilökohtainen harjoitus: FASTAXON

Ehto- ja toistolauseet

Sisältö Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 26.2

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Oliosuunnitteluesimerkki: Yrityksen palkanlaskentajärjestelmä

20. Javan omat luokat 20.1

Sisällys. 20. Javan omat luokat. Java API. Pakkaukset. java\lang

8. Näppäimistöltä lukeminen 8.1

2. Lisää Java-ohjelmoinnin alkeita. Muuttuja ja viittausmuuttuja (1/4) Muuttuja ja viittausmuuttuja (2/4)

Sisällys. 7. Oliot ja viitteet. Olion luominen. Olio Java-kielessä

Transkriptio:

Ohjelmoinnin peruskurssien laaja oppimäärä Luento 17: Scalan case class ja trait, sisäluokat, enumeraatiot Riku Saikkonen (merkityt ei-laajan kurssin kalvot: Otto Seppälä) 24. 2. 2011

Sisältö 1 Hahmonsovitus ja case class Scalassa 2 Scalan moniperintä: trait 3 Sisäluokat Javassa ja Scalassa 4 Enumeraatiot Javassa ja Scalassa 5 Lisää suunnittelumalleja

Mikä case class? (SbE 7.1) case class on muuten kuin tavallinen luokka, mutta: olioita luodessa ei tarvita new:tä metodit equals, hashcode ja tostring ovat valmiina valmis tostring tulostaa konstruktorikutsun näköisen tekstin valmis equals vertaa olion rakennetta rekursiivisesti case-luokkien kanssa voi käyttää Scalan hahmonsovitusta tarkoitettu luokille, jotka kuvaavat rakenteista dataa, usein niin että rakenteessa on useita vaihtoehtoja case-luokkaa ei yleensä peritä eikä sen kenttiä muuteta luomisen jälkeen Esimerkkikoodia abstract class Expr case class Number(n: Int) extends Expr case class Sum(e1: Expr, e2: Expr) extends Expr Sum(Number(1), Number(2)) == Sum(Number(1), Number(2)) true Sum(Sum(Number(1), Number(2)), Number(3)).toString "Sum(Sum(Number(1),Number(2)),Number(3))" (SbE 7.1)

Hahmonsovitus Scalassa (SbE 7.2) hahmonsovituksella voi sovittaa jotakin arvoa eri hahmoihin ja samalla antaa nimiä hahmon osille (ks. luento 5) syntaksi Scalassa on yleensä: arvo match { case hahmo-1 => koodia case hahmo-2 => koodia... hahmot käydään läpi järjestyksessä (kuten ifelse-if -ketju) usein hahmoilla myös luodaan uusia paikallisia muuttujia tunnistetun rakenteen osista (esimerkki alla) tämä on Scalan vastine switchille (mutta paljon monipuolisempi) Jatkoa edelliseen esimerkkiin (SbE 7.2) def eval(e: Expr): Int = e match { case Number(n) => n case Sum(l, r) => eval(l) + eval(r) eval(sum(sum(number(1), Number(2)), Number(3))) 6

Hahmot ja vahdit hahmo voi olla esimerkiksi: yksittäinen vakio case 0 =>... muuttuja ja luokka case x: Int =>... case-luokan konstruktorisyntaksin näköinen rakenne case Sum(Number(x), y) =>... pelkkä muuttujannimi tai _ sopii mihin tahansa lisäksi hahmossa voi olla vahti (guard) eli tarkistettava ehto: case Number(x) if x < 0 =>... case Sum(x,y) if x == y =>... muuttujannimen käyttäminen hahmossa tekee uuden muuttujan val x = 3; val y = 5; y match { case x => x+1 6 olemassaolevia muuttujia pitää käyttää vasta vahdissa: y match { case z if z == x => z+1; case _ => 0 4

Esimerkki case-luokista ja hahmonsovituksesta Symbolisen lausekkeen sievennystä simplify.scala abstract class Expr { def simplifystep: Expr = this match { case Sum(Num(0), x) => x.simplify // sievennyssääntöjä case Sum(x, Num(0)) => x.simplify case Product(Num(1), x) => x.simplify case Product(x, Num(1)) => x.simplify case Product(Num(0), _) => Num(0) case Product(_, Num(0)) => Num(0) case Sum(x, y) if x == y => Product(Num(2), x.simplify) case Sum(x, y) => Sum(x.simplify, y.simplify) // rekursio case Product(x, y) => Product(x.simplify, y.simplify) case x => x def simplify: Expr = { val r = this.simplifystep if (this == r) r else r.simplify // toista kunnes ei muutu case class Num(v: Int) extends Expr case class Var(name: String) extends Expr case class Sum(e1: Expr, e2: Expr) extends Expr case class Product(e1: Expr, e2: Expr) extends Expr Product(Sum(Num(0), Var("x")), Num(5)) Product(Var("x"), Num(5))

catch käyttää hahmonsovitusta myös Scalan trycatch-rakenne käyttää hahmonsovitusta hahmonsovituksen kohteena on heitetty poikkeusolio (Exception-luokan perillinen) Poikkeusesimerkki (osittainen) try { // lukee esim. rivin ''12 54'' kahteen muuttujaan val s = readline() filter { "1234567890 ".contains(_) val parts = s split ' ' filter {!_.isempty val y = parts(0).toint val x = parts(1).toint... catch { case e: IndexOutOfBoundsException => // hahmo println("i didn't understand.") // koodi case e: NumberFormatException => // toinen hahmo println("i didn't understand.") // toinen koodi

Option-luokan hahmonsovitus Scalan Option-luokkaa voi käyttää myös hahmonsovituksella Optionin perii kaksi case-luokkaa: Some(x) ja None Esimerkki Option-hahmonsovituksesta (osittainen) def findit(a: Int): Option[Int] = { var r: Option[Int] = None data foreach { item => if (found(item, a)) r = Some(item) r findit(4) match { case Some(item) =>... item... case None =>...

Parien ja monikoiden hahmonsovitus Scalan parit esim. (1,2) ja monikot esim. (1,2,3) on myös toteutettu case classeilla tämä syntaksi muuntuu valmiin case-luokan konstruktorikutsuksi, esim. Tuple2[Int,Int](1,2) matchin hahmoissa voi siis käyttää niitä: case (0, 0) =>... case (k:int, v:string) =>... case (x, y, z) =>... niillä on lisäksi metodit _1, _2, _3 jne., joilla monikon osia voi käsitellä val t = (4,5) t._1 + t._2 9 ja parin voi hajottaa osiin muuttujia määritellessä: val (x,y) = (3,5)

Sisältö 1 Hahmonsovitus ja case class Scalassa 2 Scalan moniperintä: trait 3 Sisäluokat Javassa ja Scalassa 4 Enumeraatiot Javassa ja Scalassa 5 Lisää suunnittelumalleja

trait rajapintana Javan rajapintojen vastine Scalassa on trait mutta traitissa voi olla myös metodien toteutuksia traitin syntaksi on sama kuin classin trait T {...:n toteuttaminen/periminen: class C extends T class C extends T with T2 (toteuttaa rajapinnat T ja T2) trait U extends T trait U extends T with T2 Rajapintaesimerkki (osittainen) trait Movable { def move(dx: Int, dy: Int) trait Selectable { def select() def deselect() class MyButton extends Selectable {... class MyWindow extends Movable with Selectable {... class MovableButton extends MyButton with Movable {...

Mihin muuhun traitia käytetään? koska traitissa voi olla metodien toteutuksia, sillä voi tehdä yksinkertaista moniperintää erityisesti ns. mixinejä mixin on termi luokalle, jonka perimällä toinen luokka saa lisättyä itseensä tietyn ominaisuuden osa tai kaikki metodeista on valmiina mixinissä, osan voi joutua tekemään itse periessä yleensä lisättävä ominaisuus on jonkin verran irrallinen muun luokan toiminnasta esimerkki: Scalan Ordered on trait, jossa on valmiina mm. metodit < ja <=, jotka kutsuvat compare-metodia yleensä Scalan traiteilla toteutetaan joko Java-tyylisiä rajapintoja tai pieniä mixin-luokkia

Miten traitin moniperintä toimii? traitin perivä luokka voi käyttää traitin metodeja suoraan ja ylikirjoittaa toteutuksia override-avainsanalla (samoin kuin luokkia periessä) ajattelutapa: metodit kopioidaan traitista luokkaan jos luokka perii useamman traitin, joissa on sama metodi: class A extends B with C with D kutsuttava metodi valitaan traiteista oikealta vasemmalle traitin sisällä super valitsee seuraavan vaihtoehdoista ajattelutapa: with X lisää sen edellä olevaan luokkaan X:n koodin, kuin koodi olisi kopioitu X:stä joten with X with Y lisää ensin X:n ja sitten Y:n trait voi myös periä luokan jolloin traitin koodista voi käyttää luokan metodeja mutta traitin voi ottaa mukaan vain tämän luokan aliluokkiin

Lisää traiteista Scalassa traitin voi luokan perimisen lisäksi lisätä yksittäiseen olioon konstruktoria kutsuttaessa oikeastaan tässä tehdään sisäluokka, joka perii nimetyn luokan ja toteuttaa traitin syntaksi: new-lausekkeen loppuun with trait class C {... trait T { def f() = {... val c1 = new C(...) val c2 = new C(...) with T c2.f() vielä muutama trait-yksityiskohta: abstraktia metodia toteuttaessa override ei ole pakollinen traitin konstruktorilla ei voi olla argumentteja

Sisältö 1 Hahmonsovitus ja case class Scalassa 2 Scalan moniperintä: trait 3 Sisäluokat Javassa ja Scalassa 4 Enumeraatiot Javassa ja Scalassa 5 Lisää suunnittelumalleja

Sisäluokat Sisäluokat ovat toisten luokkien luokkamäärittelyn sisällä määriteltyjä luokkia. Sisäluokkia on käytännössä neljää tyyppiä jäsenluokat (member classes) staattiset sisäluokat paikalliset sisäluokat anonyymit sisäluokat Esimerkki sisäluokan käytöstä ovat mm. java APIn HashMaprakenne joka tallentaa avain-arvo-parin Map.Entry tyyppiseen olioon. 16:54 (ei-laajan kurssin kalvo)

Sisäluokat Staattiset sisäluokat (Static nested classes) Muuten kuin tavallisia luokkia, mutta pystyvät lukemaan luokan staattisia kenttiä ja suorittamaan sen staattisia metodeja Eivät liity mihinkään ulompaan olioon! Joissakin tilanteissa tämä on erittäin kätevää Jäsenluokat (inner classes) Jäsenluokan olio liittyy aina tiettyyn ulomman luokan olioon. (enclosing instance) Se voi kutsua kaikkia tämän olion metodeita ja lukea sekä asettaa sen kaikkia kenttiä. Ulommalla oliolla on vastaavat oikeudet sisempään olioon. Ulomalla oliolla voi olla mikä tahansa määrä sisempiä olioita 16:54 (ei-laajan kurssin kalvo)

Sisäluokat Paikalliset sisäluokat (local class) Metodin tms. lohkon sisällä esiteltyä nimettyä luokkaa kutsutaan paikalliseksi sisäluokaksi. Paikallisen sisäluokan tyyppi on näkyvissä vain esittelylohkonsa sisällä. Paikallinen sisäluokka näkee ulkoluokan kentät ja metodit, mutta myös sen metodin joka sisäluokan olion loi, vakiomuuttujat Tämä estää sisäluokkaa vaikuttamasta metodin muuttujiin, jolloin vältetään mahdolliset rinnakkaisuusongelmat Vastaavasti vakiomuuttujien arvot ovat varmasti selvillä Lisäksi tämä toimii myös kun metodin suoritus on jo päättynyt Usein metodin parametrista voi tehdä vakion final-määreellä sisäluokkaa ajatellen. 16:54 (ei-laajan kurssin kalvo)

Paikalliset sisäluokat ja ympäröivät muuttujat miksi Javassa paikallinen sisäluokka näkee ympäröivästä metodista vain vakiomuuttujat? sisäluokan oliohan voidaan tallettaa jonnekin ja sitä voidaan käyttää ympäröivän metodin paluun jälkeen käytännössä sisäluokka saa automaattisesti kopion niistä ympäröivän metodin muuttujista, joita se käyttää final-muuttujilla kopion tekeminen ei haittaa (paitsi kuluttaa hiukan muistia), mutta muuten muuttujan kopioituminen olisi sekavaa, joten Java kieltää sen tämä rajoitus tulee virtuaalikoneen kutsupinon toteutuksesta kutsupino on tavallinen pino: metodin palatessa osa siitä poistetaan esim. Schemessä kutsupino on (ellei kääntäjä optimoi) linkitetty lista kehyksiä, joten yksittäisiä kutsupinon kehyksiä voidaan pitää tallessa myös funktion paluun jälkeen Scala kiertää tämän ongelman siirtämällä alkuperäisen var-muuttujan uuteen olioon (ns. boxed): osoitin tähän on vakio, joten sen voi rauhassa kopioida sisäluokkaan

Sisäluokat Anonyymit sisäluokat (anonymous inner classes) Luokille voi rakentaa lennossa aliluokkia samantapaisella menetelmällä kuin tavallisestikin. Käytännössä anonyymi sisäluokka on paikallinen luokka jolle ei anneta erillistä nimeä. Vastaavasti voidaan kirjoittaa toteutus rajapinnalle Anonyymin sisäluokan toteutus kirjoitetaan välittömästi konstruktorikutsun perään. Toteutus on kuten tavallinen luokan toteutusosa. Anonyymin sisäluokan voi tehdä kaikkialla missä voi kutsua konstruktoria Comparable Comparable vertailija vertailija = = new new Comparable(){ Comparable(){ public public int int compareto(object compareto(object o){ o){...jotain...jotain koodia... koodia... ; ; huomaa huomaa puolipiste puolipiste 16:54 (ei-laajan kurssin kalvo)

Sisäluokat Anonyymit sisäluokat Graafisissa käyttöliittymissä käytetään tyypillisesti paljon anonyymejä sisäluokkia. Tyypillisesti nämä ovat tapahtumankuuntelijoita Pikkuasioiden hoitoon ei kannata käyttää omaa tiedostoa Koodi on editoitavissa siellä missä sitä tarvitaan Päästään tarvittaessa käsiksi ulkoluokkaan 16:54 (ei-laajan kurssin kalvo)

Sisäluokat Scalassa Scalan vastine sisäluokille: objecteja ja classeja voi laittaa sisäkkäin toimivat loogisesti (muuttujat ym. leksikaalisesti sidottuja) erikoisuus: class A { class B { tekee jokaiselle A-luokan oliolle oman B-luokan (sisempi class suoritetaan konstruktorissa) Scalassa sisäluokkia käytetään vähemmän kuin Javassa monikko (tuple) korvaa Map.Entry-tyyppiset sisäluokat metodin sisäinen funktio korvaa tapahtumankuuntelijat yms. luokat (paitsi jos käyttää Java-kirjastoja, jotka haluavat luokkia eivätkä Scala-funktioita) muidenkin funktioargumenttien ja anonyymien funktioiden tilalla käytettäisiin Javassa (esim. anonyymeja) luokkia: esim. Scalan sortby ottaa funktioargumentin

Sisältö 1 Hahmonsovitus ja case class Scalassa 2 Scalan moniperintä: trait 3 Sisäluokat Javassa ja Scalassa 4 Enumeraatiot Javassa ja Scalassa 5 Lisää suunnittelumalleja

Enumeroidut tyypit Enumeroitu tyyppi, enum on tyyppi, jonka kaikki (vakio)arvot ovat tiedossa jo tyyppiä määriteltäessä enum Paiva {MAANANTAI, TIISTAI, KESKIVIIKKO...jne... enum:in arvot ovat enumeroidun tyypin staattisia kenttiä Paiva tanaan = Paiva.TORSTAI; enumeroitu tyyppi on täysin tyyppiturvallinen Paiva-tyyppinen muuttuja ei voi saada mitään muita arvoja kuin listatut vakiot ja arvon null; Enum-määrittely on pitkälti samanlainen kuin tavallisen luokan...paitsi että käytetään avainsanaa enum...ja määrittelyn pitää alkaa vakioiden listalla...ja että enumit eivät voi käyttää perintää ja ovat aina final16:54 (ei-laajan kurssin kalvo)

Enumeroidut tyypit Lisää enumeista... Enum:it voivat täyttää rajapintoja ja ovat oletusarvoisesti jo Serializable sekä Comparable Enumit voivat sisältää kenttiä, metodeja, sisäluokkia ja jopa enumeja Enumeilla on aina seuraavat metodit: public static EnumType[] values() Palauttaa enum-vakiot määrittelyjärjestyksen mukaisessa taulukossa public static EnumType valueof(string name) palauttaa merkkijonon nimisen enum-vakion 16:54 (ei-laajan kurssin kalvo)

Enumeroidut tyypit Käytännössä aiemmin nähty lista oli joukko parametrittoman konstruktorin kutsuja enum Paiva {MAANANTAI, TIISTAI, KESKIVIIKKO...jne... Jokainen enumin arvo on viittaus olioon, jonka enumin alun vakiomäärittely on luonut. Jos enumille kirjoittaa konstruktorin, voi olioden luontia ohjata tarkemmin. kts. Seuraava kalvo 16:54 (ei-laajan kurssin kalvo)

public public enum enum Paiva Paiva { { MAANANTAI( Viikko MAANANTAI( Viikko alkaa ), alkaa ), TIISTAI( uh ), TIISTAI( uh ), KESKIVIIKKO( Puolivälissä ), KESKIVIIKKO( Puolivälissä ), TORSTAI( Enää TORSTAI( Enää vähän ), vähän ), PERJANTAI( Kohta PERJANTAI( Kohta on on viikonloppu ), viikonloppu ), LAUANTAI( Huh ), LAUANTAI( Huh ), SUNNUNTAI( Kohta SUNNUNTAI( Kohta alkaa alkaa työ ); työ ); private private String String viesti; viesti; Paiva(String Paiva(String viesti) viesti) { { this.viesti this.viesti = = viesti; viesti; public public String String tostring() tostring() { { return return this.viesti; this.viesti; Kutsuu konstruktoria System.out.println(Paiva.MAANANTAI.toString()); System.out.println(Paiva.MAANANTAI.toString()); 16:54 (ei-laajan kurssin kalvo)

Enumeroidut tyypit Vakio-olioiden toimintaa voi eriyttää toisistaan sisäluokkamäärittelyä muistuttavalla syntaksilla System.out.println( System.out.println( Paiva.MAANANTAI.onkoEka()); Paiva.MAANANTAI.onkoEka()); true true System.out.println( System.out.println( Paiva.TORSTAI.onkoEka()); Paiva.TORSTAI.onkoEka()); false false public enum Paiva { public enum Paiva { MAANANTAI( Viikko alkaa ){ MAANANTAI( Viikko alkaa ){ public boolean onkoeka() { public boolean onkoeka() { return true; return true;,, TIISTAI( uh ), TIISTAI( uh ), KESKIVIIKKO( Puolivälissä ), KESKIVIIKKO( Puolivälissä ), TORSTAI( Enää vähän ), TORSTAI( Enää vähän ), PERJANTAI( Kohta on viikonloppu ), PERJANTAI( Kohta on viikonloppu ), LAUANTAI( Huh ), LAUANTAI( Huh ), SUNNUNTAI( Kohta alkaa työ ); SUNNUNTAI( Kohta alkaa työ ); private String viesti; private String viesti; Paiva(String viesti) { Paiva(String viesti) { this.viesti = viesti; this.viesti = viesti; public String tostring() { public String tostring() { return this.viesti; return this.viesti; public boolean onkoeka() { public boolean onkoeka() { return false; return false; Korvaa (overrides) vastaavan metodin enumissa Maanantain osalta 16:54 (ei-laajan kurssin kalvo)

Enumeroidut tyypit Muuta: Enumeja voi verrata suoraan == operaattorilla ja käyttää switch-lauseissa Koska enumeja ei voi periä, niitä ei voi laajentaa muuttamatta alkuperäistä enumeroitua tyyppiä Paiva alkupaiva =... Paiva alkupaiva =... if (alkupaiva == Paiva.TIISTAI) {... if (alkupaiva == Paiva.TIISTAI) {... switch (alkupaiva) { switch (alkupaiva) { case MAANANTAI: case MAANANTAI: System.out.println( MA ); System.out.println( MA ); break; break; case TIISTAI : case TIISTAI :...... Este jatkokehitykselle (täytyy koskea olemassaolevaan luokkaan perinnän sijaan) 16:54 (ei-laajan kurssin kalvo)

Enumeraatiot Scalassa Esimerkki enumeraatioista case classeilla sealed abstract class Paiva case object Maanantai extends Paiva case object Tiistai extends Paiva... p match { case Maanantai =>...; case Tiistai =>...;... Scalassa ei ole Javan enumia sen sijaan voi käyttää argumentittomia case classeja case object on tehokkaampi kuin case class (enumeraatioarvon esittämiseen käytetään aina samaa oliota) avainsana sealed kertoo, että kaikki luokan perijät on määritelty samassa tiedostossa matchissa saa virheilmoituksen, jos unohtaa jonkin tapauksista toinen tapa on periä Scalan Enumeration-luokka silloin em. virheilmoitusta ei saa mutta Enumeration-luokassa on kokoelmarajapinnan metodeita (esim. foreach), joista voi olla apua

Sisältö 1 Hahmonsovitus ja case class Scalassa 2 Scalan moniperintä: trait 3 Sisäluokat Javassa ja Scalassa 4 Enumeraatiot Javassa ja Scalassa 5 Lisää suunnittelumalleja

Decorator Mahdollistaa lisäominaisuuksien lisäämisen olioon lennossa, muuttamatta alkuperäistä luokkaa. Perusidea on, että dekoraattori liittää johonkin alkuperäiseen toimintoon oman lisänsä ja pyytää sitten koristelemaansa oliota (oli se sitten dekoraattori tai varsinainen olio) suorittamaan alkuperäisen toiminnon. Lopulta varsinainenkin operaatio tulee tehtyä Koska sekä dekoraattorit että varsinainen koristeltava olio täyttävät saman rajapinnan, ovat dekoraattorit käyttävälle luokalle näkymättömiä. Reunustaja Värittäjä TodellinenOlio Käyttävä Luokka +operaatio() +omatoiminto() +operaatio() +omatoiminto() +operaatio() 10:03 (ei-laajan kurssin kalvo)

Decorator Edellisen esimerkin UML-kaavio Käyttävä Luokka TodellinenKomponentti +operaatio() <<interface>> Komponentti +operaatio( ) <<abstract>> Dekoraattori koristettava +operaatio() +omatoiminto() operaatio(){ this.omatoiminto(); koristettava.operaatio(); Koristelija Värittäjä Reunustaja 10:03 (ei-laajan kurssin kalvo)

Decorator ja trait eräs Scalan traitien käyttötarkoitus on juuri luokan koristelu ylimääräisillä ominaisuuksilla traiteilla siis voi tehdä Decorator-suunnittelumallin yksinkertaisemmin dekoraattoriluokasta tehdäänkin trait edellä ollutta koristettava.operaatio()-kutsua vastaisi traitin koodin sisällä tehtävä super.operaatio()

Strategy Oletetaan että on olemassa joukko erilaisia tapoja ratkaista jokin laskennallinen ongelma Strategy-mallissa kirjoitetaan ensin ratkaisulle yleinen toteutus jossa vaihtoehtoiset kohdat on ulkoistettu muiden luokkien tehtäväksi Vaihtoehtoisille kohdille on kirjoitetaan rajapinta jonka kautta yleinen toteutus käyttää ulkoistettuja osia. voidaan toteuttaa erilaisia ratkaisutapoja jotka toteuttavat k.o. rajapinnan kautta jonkin osan ratkaisua, mutta ei tarvitse kirjoittaa koko koodia Nyt ratkaisutapaa voidaan haluttaessa helposti muuttaa esim. tekstin jakaminen riveihin vaihtelee kielen mukaan esim. alkioiden vertailu keskenään järjestettäessä 10:03 (ei-laajan kurssin kalvo)

Strategy import java.util.*; public class StrategyExample{ public static void main(string[] args){ Arrays.sort(args, String.CASE_INSENSITIVE_ORDER); for (int i=0; i< args.length; i++) System.out.println(args[i]); /* Vaihdetaan järjestämisstrategiaksi toisen * merkin mukaan järjestäminen */ Arrays.sort(args, new Comparator(){ public int compare(object one, Object other){ return ((String)one).charAt(1)- ((String)other).charAt(1); public boolean equals(object other){ return this.equals(other); ); System.out.println(); for (int i=0; i< args.length; i++) System.out.println(args[i]); (ei-laajan kurssin kalvo) Tässä esimerkissä järjestämisalgoritmi on kirjoitettu Arraysluokkaan. Ulkoistettu osa algoritmia on vertailu, jonka koodari voi asettaa antamalla haluamansa Comparator-olion. Esimerkissä luodaan Comparator joka järjestää merkkijonot niiden toisen merkin mukaan. 10:03

Template Method Template method toimii muuten kuin Strategy, mutta puuttuvat osat algoritmia on kirjoitettu abstrakteiksi metodeiksi Metodit toteutetaan aliluokassa jonka jälkeen algoritmi on käyttökelpoinen 10:03 (ei-laajan kurssin kalvo)

Strategy ja Template Method funktioargumenteilla edelliset kaksi suunnittelumallia muistuttavat kovasti funktioargumenttien käyttöä abstraktioiden tekemisessä tosin molemmissa luokan avulla voidaan yhdistää useampi funktioargumentti yhteen kokonaisuuteen Strategy-idean voi toki yleistää esim. moduuleihin (useita vaihtoehtoisia moduuleja, joissa on sama rajapinta)