Kurssin viimeisimmän version löydät täältä: O1: 2024
Luku 4.4: Olemattomuusharjoituksia
Tästä sivusta:
Pääkysymyksiä: Saisinko vielä lisäharjoitusta luokkien
laatimisessa, kiitos? Miten käytän itse Option
-tyyppiä?
Miten käytän itse match
-käskyä?
Mitä käsitellään? Ensisijaisesti edellisen luvun aiheita.
Mitä tehdään? Sarja pieniä ohjelmointitehtäviä. Lopussa vapaaehtoista lisämateriaalia luettavaksi.
Suuntaa antava työläysarvio:? Kolme tai neljä tuntia.
Pistearvo: A140.
Oheisprojektit: Miscellaneous, Stars (uusi), Football3 (uusi). Lisätehtävissä esiintyvät myös vanhat projektit Oliointro ja MoreApps.
Tehtävä: pieni parannus limuautomaattiin
Saatat muistaa, että luvun 3.5 lopussa hieman kyseenalaistettin laaditun
VendingMachine
-luokan metodin sellBottle
toteutusta.
Tehtävänanto
Ota tuo luokka esiin projektista Miscellaneous ja muokkaa sitä. Korvaa sellBottle
uusitulla versiolla, jonka palautusarvo on tyyppiä Option[Int]
. Metodi ei siis enää
palauta miinus ykköstä epäonnistuneen oston merkiksi. Sen sijaan metodin tulee palauttaa
None
, jos pullon myynti epäonnistui, ja Some
-olioon kääritty vaihtorahan määrä, jos
onnistui.
Palauttaminen
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Tehtävä: Member
-luokka
Tehtävänanto
Samassa Miscellaneous-projektissa on muista erillinen esimerkkiluokka o1.people.Member
.
Ota esiin sen Scaladoc-dokumentaatio ja ohjelmakoodi. Huomaat, että koodi ei vastaa
dokumentaatiota: metodit isAlive
ja toString
puuttuvat. Toteuta ne.
Vinkkejä
- Tehtävän voi ratkaista esimerkiksi
match
-käskyllä, mutta kätevämmin se ratkeaa, kun poimit pari sopivaaOption
-olioiden metodia käyttöösi edellisestä luvusta 4.3. - REPLissä kokeillessasi muista pakkaukset:
import o1.people._
.
Palauttaminen
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Tehtävä: Passenger
-luokka
Tehtävänanto
o1.people
-pakkauksen dokumentaatiosta löytyy myös matkustajia kuvaava luokka
Passenger
. Sille ei kuitenkaan ole annettu lainkaan toteutusta. Toteuta luokka.
Ohjeita ja vinkkejä
- Luokka hyödyntää toista luokkaa nimeltä
TravelCard
. Se on annettu valmiina. Älä muuta sitä. - Dokumentaatio kuvaa
Passenger
-luokan konstruktoriparametrit ja (niitä suoraan vastaavat) julkiset ilmentymämuuttujat. Tällä kertaa et tarvitse yksityisiä ilmentymämuuttujia. - Kuten dokumentaatiokin kertoo, matkustajilla tulee olla
Option[TravelCard]
-tyyppinen ilmentymämuuttuja eli jokaisella matkustajalla on nolla tai yksi matkakorttia. Tässä siis kääritäänOption
iin viittaus omatekoisen luokanTravelCard
ilmentymään. Passenger
-luokalle ei ole tarjottu tiedostoa lainkaan, joten joudut luomaan sen tyhjästä pakkaukseeno1.people
esimerkiksi näin:- Klikkaa pakkausta Eclipsen Package Explorerissa hiiren oikealla napilla ja valitse New ‣ Scala Class. Avautuu pieni ikkuna.
- Eclipse osaa pohjustaa kooditiedoston kätevästi,
kunhan syötät hieman lisätietoja. Kirjoita
Name-kohtaan luokalle nimeksi
o1.people.Passenger
. - Muita kohtia ei tarvitse muuttaa. Paina Finish. Editoriin avautuu uusi kooditiedosto, jossa on hieman alkua luokalle.
- Metodien toteutukseen löytyy työkaluja luvusta 4.3.
Palauttaminen
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Tehtävä: Tilaus
-luokan parantelu
Seuraava pieni tehtävä tarjoaa hieman lisäharjoitusta Option
-olioiden käsittelyssä
ja match
-käskyn käytössä. Mitään uutta tässä ei tule, mutta voit tehdä tehtävän, jos
äskeiset takeltelivat tai jos alempana olevia tehtäviä tehdessäsi toteat pienen
esiharjoituksen olevan paikallaan.
Lisätehtävä
Palaa Oliointro-projektin Tilaus
-luokkaan.
Luvussa 2.6 oli pieni vapaaehtoinen tehtävä,
jossa tilauksille tehtiin kuvaus
-metodin sijaan toString
-metodi.
Jos et tehnyt tuota muutosta silloin, tee se nyt: vaihda kuvaus
-metodin
nimeksi toString
ja kirjoita override
eteen.
Muokkaa sitten luokkaa seuraavasti:
- Lisää
Option[String]
-tyyppinen konstruktoriparametriosoite
ja sitä vastaavaval
-ilmentymämuuttuja. Sitä käytetään tallentamaan (mahdollinen) osoite, johon tilaus toimitetaan asiakkaan osoitteen sijaan. - Lisää parametriton, vaikutukseton metodi
toimitusosoite
, jonkaString
-tyyppinen palautusarvo kertoo, mihin tilaus toimitetaan. Se on tilaukselle erikseen kirjattu osoite, mikäli sellainen on, tai tilaajan osoite, ellei tilauksella ole erillistä osoitetta. - Muokkaa
toString
-metodia siten, että sen palauttaman merkkijonon loppuun tulee lisäksi pilkku ja välilyönti", "
sekä joko merkkijono"asiakkaan osoitteeseen"
tai"osoitteeseen X"
, missä X on tilaukselle erikseen kirjattu osoite.- (Huomaa, että
toString
-kuvauksen muodostuslogiikka on hieman erilainen kuintoimitusosoite
-funktion palautusarvon.)
- (Huomaa, että
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Tehtävä: kätevää nuolinäppäilyä
Seuraava vapaaehtoinen tehtävä on mielekäs lähinnä, jos olet jo tehnyt Trotter
-tehtävän
luvusta 3.6. Voit toki tehdä tuon aimman lisätehtävän nytkin.
Direction.fromArrowKey
o1
-pakkauksessa on Direction
-luokan lisäksi samanniminen yksittäisolio. Sillä on kätevä metodi fromArrowKey
, joka toimii
tähän tapaan:
val exampleKey = Key.UpexampleKey: o1.Key.Value = Up Direction.fromArrowKey(exampleKey)res0: Option[Direction] = Some(Direction.Up) Direction.fromArrowKey(Key.X)res1: Option[Direction] = None
Metodi siis palauttaa näppäintä vastaavan suunnan. Apuna se käyttää Option
-luokkaa,
koska vain osaa näppäimistä vastaa jokin suunta.
Muokkaa MoreApps-projektin TrotterApp
-ohjelman onKeyDown
-metodia. Sen pitää
toimia kuin ennenkin, mutta saanet tehtyä sille aiempaa yksinkertaisemman ja vähemmän
toisteisen toteutuksen, kun käytät fromArrowKey
-metodia.
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Tähtikarttatehtävä, osa 1/4: tähden perustiedot
Johdanto: tähtiä koordinaatistoissa
Laaditaan ohjelma, jolla voi kuvata tähtikarttoja eli näkymiä tähtitaivaasta. Kuhunkin tähtikarttaan sisältyy tähtiä; lisäksi tähtiä voi (kunhan ohjelmamme aikanaan valmistuu) yhdistää toisiinsa muodostaen tähtikuvioita.
Tässä tehtäväsarjan ensimmäisessä osassa ei vielä piirretä mitään, vaan luodaan väline yksittäisten tähtien tietojen mallintamiseksi.
Nouda projekti Stars. Nyt ajankohtaisia luokkia ovat Star
ja StarCoords
, joista
ensimmäisen tulet itse toteuttamaan jälkimmäistä valmiina annettua luokkaa apuna käyttäen.
Lue näiden luokkien dokumentaatio; älä välitä muista luokista.
Kuten dokumentaatiokin kertoo, tämä ohjelma käsittelee kahdenlaisia kaksiulotteisia koordinaatteja:
- Kunkin tähden sijainti tähtikartalla kuvataan
StarCoords
-tyyppisenä koordinaattiparina.- Tässä yhteydessä käytämme matematiikasta tuttua koordinaatistoa, jossa y-arvot kasvavat yläreunaa kohden.
- Sekä x- että y-arvot on normalisoitu välille [-1.0...+1.0]; ks. kuva. Nämä arvot kuvaavat tähden sijaintia näkyvällä taivaalla riippumattomasti siitä, minkäsuuruiseen kuvaan tähtikartta mahdollisesti piirretään.
- Toisaalta
Star
-luokan metoditoImagePos
-metodi osaa tuottaaPos
-tyyppisen koordinaattiparin, joka kuvaa tähden sijaintia tähtikartan kuvassa. Nämä koordinaatit kasvavat graafiselle ohjelmoinnille tyypilliseen tapaan kuvan vasemmassa yläkulmassa sijaitsevasta origosta oikealle ja alas. Ne kertovat suoraan, mihin pikseliin tähden kuvan keskipiste tulisi piirtää, jos tähtitaivasta kuvataan tietynkokoisena kuvana.
Tehtävänanto
- Varmista yllä olevan kuvauksen ja dokumentaation perusteella,
että ymmärrät käytetyt kaksi koordinaatistoa. Varmista, että
ymmärrät, mitä
StarCoords
-luokantoImagePos
-metodi tekee. - Toteuta sitten luokan
Star
puuttuvat metodit dokumentaation mukaisiksi.
Ohjeita ja vinkkejä
Star
-luokan pitäisi siis lopulta toimia tähän tapaan:import o1.stars._import o1.stars._ val unnamedStar = new Star(28, new StarCoords(0.994772, 0.023164), 4.61, None)unnamedStar: o1.stars.Star = 28 (x=0.99, y=0.02) unnamedStar.posIn(rectangle(100, 100, Black))res2: o1.world.Pos = (99.7386,48.8418) unnamedStar.posIn(rectangle(200, 200, Black))res3: o1.world.Pos = (199.4772,97.6836) val namedStar = new Star(48915, new StarCoords(-0.187481, 0.939228), -1.44, Some("SIRIUS"))namedStar: o1.stars.Star = 48915 SIRIUS (x=-0.19, y=0.94)
Sinun ei varsinaisesti tarvitse itse toteuttaa tarvittavaa matematiikkaa, kun hyödynnät
StarCoords
-luokkaa.Sinun ei myöskään tarvitse pyöristää itse tähden koordinaatteja, vaikka
toString
-metodin tuleekin ne pyöristettyinä esittää.StarCoords
-luokantoString
-metodi hoitaa homman puolestasi, kunhan käytät sitä.
Palauttaminen
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Tähtikarttatehtävä, osa 2/4: tähdet kuvaksi
Tehtävänanto
Stars-projektiin kuuluu yksittäisolio o1.stars.io.SkyPic
, jonka metodeilla voi muodostaa
kuvia tähtikartoista. Tässä pikkutehtävässä keskitytään metodiin placeStar
. Sille voi
antaa kuvan ja tähden ja se palauttaa uusitun version kuvasta, johon myös kyseinen tähti
on piirretty.
Sanotaan vaikkapa, että haluamme kuvan, johon on piirretty nämä kaksi tähteä:
val unnamedStar = new Star(28, new StarCoords(0.994772, 0.023164), 4.61, None)unnamedStar: o1.stars.Star = 28 (x=0.99, y=0.02) val namedStar = new Star(48915, new StarCoords(-0.187481, 0.939228), -1.44, Some("SIRIUS"))namedStar: o1.stars.Star = 48915 SIRIUS (x=-0.19, y=0.94)
Homman pitäisi järjestyä näin:
val darkBackground = rectangle(500, 500, Black)darkBackground: Pic = rectangle-shape val skyWithOneStar = SkyPic.placeStar(darkBackground, unnamedStar)skyWithOneStar: Pic = combined pic val skyWithTwoStars = SkyPic.placeStar(skyWithOneStar, namedStar)skyWithTwoStars: Pic = combined pic skyWithTwoStars.show()
Tuo placeStar
-metodi on kuitenkin toteuttamatta. Lue sen spesifikaatio dokumentista ja
toteuta metodi tiedostoon SkyPic.scala
merkittyyn kohtaan.
Ohjeita ja vinkkejä
- Tehtävässä ei ole mitään vaikeaa, kunhan hyödynnät edellisen tehtävän esittelemää työkalustoa.
- Tehtävän tehtyäsi voit todeta, että noin niitä yksittäisiä tähtiä
tosiaan kuvaan saa, mutta kovin kätevää kuvan luominen ei ole,
jos tähtiä pitäisi saada esiin muutamaa enemmän.
- Kätevämpää olisi, jos tähtien tiedot voisi ladata kerralla jostakin, mihin ne on kirjattu. Niin pian teemmekin.
- Voit jo silmäillä kansioiden
test
janorthern
sisältöä, erityisesti niistä löytyviästars.csv
-tiedostoja. - Palaamme asiaan luvussa 5.2.
Palauttaminen
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Football3-tehtävä
Futistulosohjelmamme (luvusta 3.5) meni jo kerran uusiksi (luvussa 4.2), ja nyt niin käy taas.
Tehtävänanto
Nouda projekti Football3. Tutustu sen dokumentaatioon. Luokan Match
spesifikaatio on
nyt osin erilainen kuin ennen, ja luokka Season
on uusi tuttavuus.
Laadi näille luokille dokumentaation mukaisesti toimivat toteutukset.
Ohjeita ja vinkkejä
- Voit kopioida
Match
-luokan toteutuksen pohjaksi Football2-projektiin laatimasi koodin. Nyt laadittavaksi pyydetty versio poikkeaa siitä vain näin:winnerName
-metodin lisäksi on metodiwinner
, joka palauttaaOption
-arvon.winningScorerName
-metodia ei enää ole; sen tilalle tulee metodiwinningScorer
, joka palauttaaOption
-arvon.
- Kun
winner
-metodisi toimii, kokeile käyttää sitä apuna laatiaksesi yksinkertaisemman toteutuksenwinnerName
-metodille. - Muista:
Match
isolla on ottelua kuvaavalle luokalle valittu nimi.match
pienellä on Scalan käsky (jota ei voi käyttää nimenä; se on varattu sana). Näiden sotkeminen toisiinsa voi tuottaa jännittäviä virhetilanteita. - Voit jälleen käyttää testausapuna annettua
FootballApp
-ohjelmaa. KunSeason
-luokka on tehty, ohjelma näyttää pääikkunassaan kauden tilastoja ja otteluluettelon. Season
-luokkaa toteuttaessasi voi olla apua lukujen 4.2 ja 4.3 ja GoodStuff-projektin tutkimisesta.- Suurimman voiton (
biggestWin
) selvittämisessä voit hyödyntääOption
-tyyppistä ilmentymämuuttujaa sopivimman säilyttäjän roolissa samaan tapaan kuin teimmeCategory
-luokassa. - Suuremmuusongelman voi ratkaista myös toisilla ohjelmointitekniikoilla, joita ei ole vielä kurssilla käsitelty (esim. toistokäskyt; luku 5.5). Niiden käyttö on kyllä sallittua, jos satut ennestään osaamaan, mutta ei välttämätöntä.
- Suurimman voiton (
- Huomasithan, että otteluiden
goalDifference
-metodi voi palauttaa myös negatiivisen luvun?
Palauttaminen
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.
Pohdittavaa
Dokumentaatiossa erikseen sanottiin, että Season
-olioon lisättävien
otteluiden oletetaan jo päättyneen eikä niihin siis enää saa lisätä
maaleja. Mitä tapahtuu, jos tätä oletusta rikotaan? Miten vastaavan
sovelluksen voisi laatia niin, ettei tuota vaaraa ole?
Lisämateriaalia: monipuolinen match
-käsky
Seuraavat laatikot kertovat lisää match
-käskystä, jota olemme käyttäneet
Option
-olioiden käsittelyyn. Tämä ei ole kurssin kannalta keskeistä asiaa mutta
kiinnostanee ainakin niitä aiemmin ohjelmoineita lukijoita, jotka haluavat nyt oppia
Scala-kieltä mahdollisimman monipuolisesti. Aloitteleva ohjelmoija voi mainiosti ohittaa
seuraavan ja opetella nämä asiat joskus myöhemmin.
match
on hahmonsovituksen työkalu
match
-käskyn yleinen muoto on:
lauseke L match { case hahmo A => koodia, joka suoritetaan, jos L:n arvo sopii hahmoon A case hahmo B => koodia, joka suoritetaan, jos L:n arvo sopii hahmoon B (muttei A:han) case hahmo C => koodia, joka suoritetaan, jos L:n arvo sopii hahmoon C (muttei A:han tai B:hen) Ja niin edelleen. (Usein katetaan kaikki mahdolliset tapaukset.) }
None
- ja
Some
-hahmoja, mutta tässä kohden voi käyttää
monenmoisia muitakin eri hahmoja, joista eräitä
on esitelty alla.Alkeellista match
äystä literaaleilla
Oletetaan, että on Int
-tyyppinen muuttuja nimeltä luku
. Tutkitaan
vaikkapa lausekkeen luku * luku * luku
arvoa match
-käskyllä:
val kuutionKuvaus = luku * luku * luku match {
case 0 => "luku on nolla ja niin sen kuutiokin"
case 1000 => "kympistä tulee tuhat"
case muuKuutio => "luku " + luku + ", jonka kuutio on " + muuKuutio
}
Int
-literaaleja. Näistä tapauksista
ensimmäinen valitaan, jos luvun kuutio oli
nolla, toinen jos se oli tuhat.muuKuutio
. Tällainen
tapaus sopii yhteen minkä tahansa arvon kanssa
ja tulee siis tässä valituksi mikäli kuutio ei
ollut nolla eikä tuhat.Tässä vielä vastaava esimerkki, jossa Int
-literaalien sijaan käsitellään
Boolean
-literaaleja. Seuraavat koodinpätkät saavat aikaan ihan saman:
if (luku < 0) "negatiivinen" else "ei negatiivinen"
luku < 0 match {
case true => "negatiivinen"
case false => "ei negatiivinen"
}
Kaiken äskeisen saa aikaan luvusta 3.4 tutuilla if
–else
-ketjuillakin. Näin
yksinkertaisesti käytettynä match
ei vielä ihan pääse oikeuksiinsa. Mutta luepa
alta lisää.
Kysyttyä: onko match
-käsky suunnilleen sama kuin esim. Javan switch
?
Javassa ja joissakin muissa kielissä on switch
-niminen käsky,
jolla voi valita yhden useasta vaihtoehdosta sillä perusteella, mikä
nimenomainen arvo tietyllä lausekkeella on.
Scalan match
illä on yhtäläisyyksiä tuon käskyn kanssa. Kuitenkin
switch
pystyy ainoastaan valitsemaan tapauksen, joka vastaa
yksittäistä arvoa (kuten kuutionKuvaus
-esimerkissämme) kun taas
match
tarjoaa monipuolisempia mahdollisuuksia hahmonsovitukseen.
Erityisen huomionarvoista on, että match
-käskyllä voi:
- tehdä valinnan tyypin perusteella, ja
- "purkaa" tarkasteltavan olion hahmon mukaisesti ja poimia olion osia paikallisiin muuttujiin.
Muun muassa näistä mahdollisuuksista on esimerkkejä alla.
Lisäehto tapaukselle
Hahmon yhteyteen voi määritellä lisäehdon (pattern guard), jonka pitää myös täyttyä, jotta kyseinen tapaus tulisi valituksi.
val kuutionKuvaus = luku * luku * luku match {
case 0 => "luku on nolla ja niin sen kuutiokin"
case 1000 => "kympistä tulee tuhat"
case muu if muu > 0 => "positiivinen kuutio " + muu
case muu => "negatiivinen kuutio " + muu
}
match
-käskyn osana samaa if
-sanaa kuin
tutussa erillisessä if
-valintakäskyssäkin.Alaviiva match
-hahmoissa
Alaviivaa voi käyttää match
-käskyssä tarkoittamaan "mikä vain"
tai "ei väliä mikä". Tässä pari esimerkkiä:
luku * luku * luku match {
case 0 => "luku on nolla ja niin sen kuutiokin"
case 1000 => "kympistä tulee tuhat"
case _ => "joku muu kuin nolla tai tuhat"
}
match
äystä tyypin mukaan
Äskeisissä esimerkeissä hahmot vastasivat erilaisia mutta keskenään samantyyppisiä arvoja. Seuraavassa hahmot ovat keskenään erityyppisiä:
def kokeilu(jonkinlainenArvo: Any) =
jonkinlainenArvo match {
case jono: String => "kyseessä on merkkijono " + jono
case luku: Int if luku > 0 => "kyseessä on positiivinen kokonaisluku " + luku
case luku: Int => "kyseessä on ei-positiivinen kokonaisluku " + luku
case vektori: Vector[_] => "kyseessä on vektori, jossa on " + vektori.size + " alkiota"
case _ => "kyseessä on jokin sekalainen arvo"
}
Any
, mikä tarkoittaa
että sille voi antaa minkä tahansa tyyppisen arvon parametriksi.
(Lisää Any
stä luvussa 7.3.)vektori
-niminen muuttuja on Vector
-tyyppinen,
ja sen kautta voimme esimerkiksi kutsua vektorien size
-metodia.Olion "purkaminen" match
-käskyllä
Yksi match
-käskyn näppärimmistä ominaisuuksista on, että hahmossa voi
"purkaa" tutkittavan olion, mikäli se sopii kyseiseen hahmoon, ja poimia
sen osia talteen muuttujiin. Yksinkertainen esimerkki tästä on tuttu
Some
-kääreen "purkaminen":
lukuvektori.lift(4) match {
case Some(kaaritty) => "luku " + kaaritty
case None => "ei lukua"
}
Some
, niin sen sisällä on jokin arvo. Tuo
arvo "puretaan esiin" ja poimitaan muuttujaan
kaaritty
.Tätä tekniikkaa sopii yhdistellä muihin esiteltyihin. Alla puretaan Option
ja samalla koetetaan sovittaa sen mahdollinen sisältö johonkin useasta eri
tapauksesta:
lukuvektori.lift(4) match {
case Some(100) => "nimenomaan luku sata"
case Some(kaaritty) if kaaritty % 2 == 0 => "muu parillinen luku " + kaaritty
case Some(pariton) => "pariton luku " + pariton
case None => "ei lukua"
}
Olion "purkaminen" on mahdollista vain, jos kyseiselle luokalle on määritelty,
miten sentyyppiset olio puretaan. Tällainen määrittely on monilla Scalan valmiilla
luokilla, esimerkiksi Some
-olioilla. Vastaavasti O1-kirjaston Pos
-tyypille on
määritelty, että sen voi purkaa kahdeksi koordinaatiksi kuten tässä:
jokuPos match {
case Pos(x, y) if x > 0 => "koordinaatit, joiden x on positiivinen ja y on " + y
case Pos(_, y) => "muu koordinaattipari, jossa y on " + y
}
Pos
, se on purettavissa kahdeksi
luvuksi. Tallenna ne paikallisiin muuttujiin x
ja y
.
Jos näistä x
on positiivinen, valitaan tämä tapaus."Pos
kahdeksi luvuksi, joista ensimmäisellä voi
heittää vesilintua ja toinen tallennetaan paikalliseen
muuttujaan y
." Tämä hahmo sopii kaikkiin mahdollisiin
Pos
-arvoihin ja tulee väistämättä valituksi, jos
ensimmäinen tapaus ei tärpännyt.Miten purkamistapa sitten määritellään? Helpoin tapa on tehdä luokasta ns. tapausluokka (case class), mistä on tässä yksinkertainen esimerkki:
case class Album(val name: String, val artist: String, val year: Int) {
// ...
}
case
.match
-käskyllä voi
olion purkaa. Albumiolion voi purkaa nimeksi,
artistiksi ja vuodeksi.Käyttöesimerkki:
jokinAlbumiolio match {
case Album(_, _, vuosi) if vuosi < 2000 => "muinainen"
case Album(nimi, tekija, vuosi) => tekija + ": " + nimi + " (" + vuosi + ")"
}
Lisätietoja löytyy netistä esimerkiksi hakusanoilla Scala pattern matching ja Scala case class. Kuten todettu, O1-kurssin puitteissa tässä esiteltyjä Scala-kielen ominaisuuksia ei ole pakko osata käyttää.
Lisämateriaalia: Option
-olioiden get
-metodista
Tässä vapaaehtoisessa kappaleessa esitellään eräs Option
-olioiden metodi, joka voi
vaikuttaa petollisen kätevältä mutta jonka käyttöä kannattaa välttää.
Vaarallinen get
-metodi
Yksi tapa avata Option
-kääre on kutsua sen parametritonta get
-metodia. Kokeile
itse.
Esimerkiksi Category
-luokan addExperience
-metodissa olisimme periaatteessa voineet
käyttää tätä metodia match
-käskyn sijaan:
def addExperience(newExperience: Experience) = {
this.experiences += newExperience
val newFave =
if (this.fave.isEmpty)
newExperience
else
newExperience.chooseBetter(this.fave.get)
this.fave = Some(newFave)
}
isEmpty
-metodilla.Option
-kääreestä. Tämä tehdään
vain else
-haarassa, joten on varmaa, että kyseessä ei ole
None
-arvo.Option
-olion get
-metodissa kuitenkin piilee osa samasta vaarasta kuin
null
-viittauksissakin: jos metodia kutsuu None
-arvolle, syntyy ajonaikainen
poikkeustilanne. Jää ohjelmoijan muistettavaksi, että ennen get
-metodin kutsumista
pitää aina varmistaa, että Option
-arvolla todella on sisältö. Tämä unohtuu
helposti.
Opiskelijan sanoin:
Ainakaan sitä ei kannata rynnätä suin päin avaamaan kuten get
tekee. Avatessa
kannattaa varautua mahdolliseen pettymykseen, ettei tule itku.
On ihan hyvä tietää, että get
-metodi on olemassa. Saatat nähdä sitä käytetyn
muiden laatimissa ohjelmissa. Jätä itse metodi käyttämättä. Sen voi aina korvata
paremmalla ratkaisulla, esimerkiksi match
-käskyllä tai getOrElse
-metodikutsulla.
Palaute
Huomaathan, että tämä on henkilökohtainen osio! Vaikka olisit tehnyt lukuun liittyvät tehtävät parin kanssa, täytä palautelomake itse.
Tekijät
Tämän oppimateriaalin kehitystyössä on käytetty apuna tuhansilta opiskelijoilta kerättyä palautetta. Kiitos!
Kierrokset 1–13 ja niihin liittyvät tehtävät ja viikkokoosteet on laatinut Juha Sorva.
Kierrokset 14–20 on laatinut Otto Seppälä. Ne eivät ole julki syksyllä, mutta julkaistaan ennen kuin määräajat lähestyvät.
Liitesivut (sanasto, Scala-kooste, usein kysytyt kysymykset jne.) on kirjoittanut Juha Sorva sikäli kuin sivulla ei ole toisin mainittu.
Tehtävien automaattisen arvioinnin ovat toteuttaneet: (aakkosjärjestyksessä) Riku Autio, Nikolas Drosdek, Joonatan Honkamaa, Jaakko Kantojärvi, Niklas Kröger, Teemu Lehtinen, Strasdosky Otewa, Timi Seppälä, Teemu Sirkiä ja Aleksi Vartiainen.
Lukujen alkuja koristavat kuvat ja muut vastaavat kuvituskuvat on piirtänyt Christina Lassheikki.
Yksityiskohtaiset animaatiot Scala-ohjelmien suorituksen vaiheista ovat suunnitelleet Juha Sorva ja Teemu Sirkiä. Niiden teknisen toteutuksen ovat tehneet Teemu Sirkiä ja Riku Autio käyttäen Teemun toteuttamia Jsvee- ja Kelmu-työkaluja.
Muut diagrammit ja materiaaliin upotetut vuorovaikutteiset esitykset on laatinut Juha Sorva.
O1Library-ohjelmakirjaston ovat kehittäneet Aleksi Lukkarinen ja Juha Sorva. Useat sen keskeisistä osista tukeutuvat Aleksin SMCL-kirjastoon.
Opetustapa, jossa käytämme O1Libraryn työkaluja (kuten Pic
) yksinkertaiseen graafiseen
ohjelmointiin on saanut vaikutteita tekijöiden Flatt, Felleisen, Findler ja Krishnamurthi
oppikirjasta How to Design Programs sekä Stephen Blochin oppikirjasta Picturing Programs.
Oppimisalusta A+ on luotu Aallon LeTech-tutkimusryhmässä pitkälti opiskelijavoimin. Pääkehittäjänä toimii tällä hetkellä Jaakko Kantojärvi, jonka lisäksi järjestelmää kehittävät useat tietotekniikan ja informaatioverkostojen opiskelijat.
Kurssin tämänhetkinen henkilökunta on kerrottu luvussa 1.1.
Joidenkin lukujen lopuissa on lukukohtaisia lisäyksiä tähän tekijäluetteloon.
match
-käskyllä voi tutkia minkä tahansa lausekkeen arvoa. Teknisemmin sanoen kyseessä on hahmonsovitus (pattern matching): lausekkeen arvoa verrataan...