Muutettu viimeksi 21.4.2010 / Sivu luotu 14.4.2010 / [oppikirjan esimerkit] / [Scala]
Sivun sisältöä:
final def ==(that: Any): Boolean final def !=(that: Any): Boolean def equals(that: Any): Boolean def hashCode: Int def toString: StringKuten näkyy, mikään luokka ei voi korvata yhtäsuuruus- ja erisuuruusoperaatiota (final), mutta equals-metodia sitä sitten korvataankin... Oletustoteutus on Javan tapaan oliosamuus.
Operaatiot == ja != kuitenkin tavalla tai toisella johtavat equals-vertailuun ja siten polymorfismin ansiosta niitä voidaan käyttää myös itse ohjelmoidun samuuden vertailuun. Ymmärtääkseni nuo kaksi operaatiota on ohjelmoitu siten, että ne kutsuvat equalsia. Mitenkäs muutenkaan?
Jo kurssin alussa kuultiin se ilosanoma, että merkkijonoja Scalassa voi (järkevästi) vertailla operaatioilla == ja !=.
Huom: Kun ohjelmoi omalle luokalleen equals-metodin, on syytä pitää huoli, että toteuttaa ekvivalenssirelaation ja myös että samaistettavien olioiden hashCode on sama, ks. API.
Metodi toString Javan tapaan antaa oletusarvoisen "teknisen" tulostusasun kaikkien luokkien ilmentymille. Tapana on korvata.
Lukuunottamatta viimeistä nuo vastaavat Javan alkeistyyppejä. Myös ohjelman suoritusaikana ne (useimmiten) voidaan toteuttaa alla lymyävän Javan tapaan.
Scalassa myös Javan alkeistyyppien vastineiden ajatellaan olevan olioita. Niitä ei kuitenkaan konstruoida tyyliin new Int(5). Ainoa tapa luoda tällaisia olioita on kirjoittaa ne ohjelmaan literaaleina: 345, 3.14, false. Teknisesti asia on hoideltu määrittelemällä nuo luokat abstrakteiksi.
Luokalla Unit on vain yksi ilmentymä: (). Se on kaikkien "arvoa palauttamattomien" "funktioiden" arvo...
Koska esimerkiksi siis Int on Anyn aliluokka, se perii Anyn kaluston:
println(4321.toString) // 4321 println(4321 hashCode) // 4321 println(4321 equals (4000+321)) // true
Matematiikasta poiketen "pienet kokonaisluvut" eivät ole "kokonaislukujen" osajoukko (aliluokka), "kokonaisluvut" eivät ole "reaalilukujen" osajoukko (aliluokka), jne. Itse asiassa tietokoneessa näiden tyyppien sisäiset esitykset ovatkin aidosti erilaisia. Tätä heijastellee myös Scalan valinta esittää numeeriset tyypit rinnakkaisina periytymishierarkiassa.
Javasta tutut "sallitut sijoitukset", implisiittiset tyyppimuunnokset, tiettyjen numeeristen tyyppien välillä ovat käytössä myös Scalassa. Kannattaa muuten huomata, että nämä todellakin aiheuttavat töitä myös ohjelman suoritusaikana.
Piirteet ("trait") tuovatkin sitten oman lisävärinsä asioihin. Kuvassa näkyi jo ScalaObject, jota käytetään joihinkin käännösteknisiin jippoihin...
Kaikkien Scalan luokkien yhteinen aliluokka on sitten se vihoviimeinen Nothing. Se on sikälikin nimensä mukainen, ettei siitä ole olemassa ainuttakaan ilmentymää.
Mihin sellaista voi käyttää? No sitä voi käyttää tyyppinä! Jos vaikkapa funktion tyyppi on Nothing, tuon funktion voi sijoittaa minne tahansa, minne jonkin arvon voi sijoittaa.
Luvussa 7 nähtiin "Scala-knoppologiaa": Scalassa (melkein) kaikella on arvo. Niin myös throw-ilmauksella:
val n = readInt val half = if (n % 2 == 0) n / 2 else throw new RuntimeException("n must be even")Mitään arvoahan ei muuttujalle half aseteta, jos n on pariton. Vahvasti tyypitetyssä kielessä "arvoilla" pitää kuitenkin aina olla tyyppi. Teknisesti throw-lause on tyypiltään Nothing, joka on kaikkien Scalan tyyppien alityyppi. Tässä esimerkissä se tarkoittaa, että Nothing kelpaa esim. juuri Int-tyypin arvoksi!
Tulipa muuten kokeiltua:
val n = readInt val half = if (n % 2 == 0) n / 2 else println("n must be even") println(n)Toimii! Lauseen println tyyppi on Unit ja halfin tyypiksi tulee tässä AnyVal. (Korjattu 21.4. virheellinen väite, että println olisi tyypiltään Nothing! Kiitokset opiskelija Onni Koskiselle!)
Vielä yksi järkevä esimerkki: Scalan standardikirjastossa on metodi
def error(message: String): Nothing = throw new RuntimeException(message)jota voi käyttää tyyliin:
def divide(x: Int, y: Int): Int = if (y != 0) x / y else error("can't divide by zero")Tässäkin Nothing-tyyppinen funktio kelpaa Int-arvoksi.
(Hmm. Nothingin tyylikkyydestä sitten voi olla ainakin kahta mieltä. En ole vielä omaa kantaani valinnut.)