Ohjelmoinnin peruskurssien laaja oppimäärä

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

15. Ohjelmoinnin tekniikkaa 15.1

15. Ohjelmoinnin tekniikkaa 15.1

16. Javan omat luokat 16.1

Java kahdessa tunnissa. Jyry Suvilehto

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

Ohjelmoinnin peruskurssien laaja oppimäärä

Rajapinta (interface)

Oliot ja tyypit. TIES542 Ohjelmointikielten periaatteet, kevät Antti-Juhani Kaijanaho. Jyväskylän yliopisto Tietotekniikan laitos

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

Ohjelmoinnin peruskurssien laaja oppimäärä

Listarakenne (ArrayList-luokka)

Ohjelmoinnin peruskurssien laaja oppimäärä

Taulukot. Jukka Harju, Jukka Juslin

12. Monimuotoisuus 12.1

Taulukot. Taulukon määrittely ja käyttö. Taulukko metodin parametrina. Taulukon sisällön kopiointi toiseen taulukkoon. Taulukon lajittelu

Ohjelmoinnin jatkokurssi, kurssikoe

Ohjelmistojen mallintaminen viikon 4 laskareiden mallivastauksia

Informaatioteknologian laitos Olio-ohjelmoinnin perusteet / Salo

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

Luokan sisällä on lista

Groovy. Niko Jäntti Jesper Haapalinna Group 31

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

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

Javan perusteita. Janne Käki

9. Periytyminen Javassa 9.1

Ohjelmoinnin perusteet, syksy 2006

Ohjelmoinnin perusteet Y Python

1. Omat operaatiot 1.1

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

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

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

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

Olio-ohjelmointi Javalla

tään painetussa ja käsin kirjoitetussa materiaalissa usein pienillä kreikkalaisilla

ELM GROUP 04. Teemu Laakso Henrik Talarmo

Kääreluokat (oppikirjan luku 9.4) (Wrapper-classes)

Java-kielen perusteet

Ohjelmoinnin peruskurssien laaja oppimäärä

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

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä, kevät

Algebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005

12. Monimuotoisuus 12.1

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä. Tiedonkätkentä. Aksessorit. 4.2

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

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä ja ulkopuolelta. Attribuuttien arvojen käsittely aksessoreilla. 4.2

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

Geneeriset tyypit. TIES542 Ohjelmointikielten periaatteet, kevät Antti-Juhani Kaijanaho. Jyväskylän yliopisto Tietotekniikan laitos

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

815338A Ohjelmointikielten periaatteet Harjoitus 7 Vastaukset

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

Aalto Yliopisto T Informaatioverkostot: Studio 1. Oliot ja luokat Javaohjelmoinnissa

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

9. Periytyminen Javassa 9.1

Oliosuunnitteluesimerkki: Yrityksen palkanlaskentajärjestelmä

14. Poikkeukset 14.1

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

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

Ohjelmoinnin peruskurssi Y1

Ohjelmointi 2 / 2010 Välikoe / 26.3

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssien laaja oppimäärä

812341A Olio-ohjelmointi Peruskäsitteet jatkoa

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

C++11 Syntaksi. Jari-Pekka Voutilainen Jari-Pekka Voutilainen: C++11 Syntaksi

Ohjelmoinnin perusteet, kurssikoe

Luokan muodostimet (Constructors)

Tietorakenteet, laskuharjoitus 7,

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

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

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

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Sisällys. 11. Rajapinnat. Johdanto. Johdanto

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

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

Tietorakenteet, laskuharjoitus 8, malliratkaisut

Se mistä tilasta aloitetaan, merkitään tyhjästä tulevalla nuolella. Yllä olevassa esimerkissä aloitustila on A.

Ohjelmoinnin perusteet Y Python

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

14. Poikkeukset 14.1

Pythonin Kertaus. Cse-a1130. Tietotekniikka Sovelluksissa. Versio 0.01b

Osoitin ja viittaus C++:ssa

Sokkelon sisältö säilötään linkitetyille listalle ja tekstitiedostoon. Työ tehdään itsenäisesti yhden hengen ryhmissä. Ideoita voi vaihtaa koodia ei.

11/20: Konepelti auki

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

Ohjelmoinnin perusteet Y Python

7/20: Paketti kasassa ensimmäistä kertaa

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

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

Geneeriset luokat. C++ - perusteet Java-osaajille luento 6/7: Template, tyyppi-informaatio, nimiavaruudet. Geneerisen luokan käyttö.

Ohjelmoinnin peruskurssien laaja oppimäärä

Metodien tekeminen Javalla

Ohjelmoinnin peruskurssien laaja oppimäärä

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

Transkriptio:

Ohjelmoinnin peruskurssien laaja oppimäärä Luento 16: Generics Javassa ja Scalassa Riku Saikkonen (merkityt ei-laajan kurssin kalvot: Otto Seppälä) 16. 2. 2011

Sisältö 1 Generics Javassa ja Scalassa 2 Generics-yksityiskohtia 3 Taustaa geneerisistä tyypeistä

Generics Java-kielen versiossa 5 kieleen lisättiin tuki geneerisille tyypeille Mahdollistavat luokan tai metodin sisältämien muuttujien ja paluuarvojen tyypin määrittämisen tapauskohtaisesti käyttämällä tyyppiparametreja Vähentävät tarvetta suorittaa tyyppipakotusta luokan ulkopuolella Esim Javan version 4 ArrayList säilöi vain Object-viittauksia jotka piti tyyppipakottaa rakenteesta otettaessa Vähentävät samalla ajonaikaisia tyyppipakotusvirheitä (ClassCastException) koska generics:it hoidetaan jo käännösvaiheessa 16:54

Generics Allaoleva rivi luo ArrayList:in joka säilöö String-olioita ArrayList<String> sanalista ArrayList<String>(); Tässä String on tyyppiparametrille annettava arvo Määritelmästä johtuen sanalistan add-metodi hyväksyy vain Stringluokan olioita parametrikseen aliluokan tai alirajapinnankin oliot kelpaavat. String:illä vaan ei ole aliluokkia eikä sitä voi periä koska luokka on final. ArrayList<String> ArrayList<String> sanalista sanalista ArrayList<String>(); ArrayList<String>(); sanalista.add( Hei sanalista.add( Hei vaan! ); vaan! ); String String sana sana sanalista.get(0); sanalista.get(0); 16:54

Geneerinen Luokka Seuraava pätee sekä luokille, että rajapinnoille,mutta yksinkertaisuuden vuoksi puhumme seuraavassa vain luokista Geneerisessä luokassa on aina yksi tai useampi tyyppiparametri Tyyppiparametrille annetaan jokin muuttujanimi, joka korvataan käännösaikaisesti oikeilla tyypeilla (esimerkissämme tämän tyyppimuuttujan nimi on OmaTyyppi) Luokkamäärittelyn yhteydessä tyyppiparametri esitellään < ja >- merkkien välissä heti luokan nimen jälkeen Muuuttujan kautta käytettävää tyyppiä voi tämän jälkeen käyttää luokassa esim. muuttujien ja paluuarvojen tyyppinä class class OmaLista<OmaTyyppi> OmaLista<OmaTyyppi> OmaTyyppi OmaTyyppi vaihdaalkio(omatyyppi vaihdaalkio(omatyyppi uusialkio) uusialkio)...... jne. jne. 16:54

Esimerkki Luokka jolla voi tallentaa millaisen tahansa olioparin. class class Pair Pair <FirstType, <FirstType, SecondType> SecondType> Pair(FirstType Pair(FirstType first, first, SecondType SecondType second) second) this.first this.first first; first; this.second this.second second; second; FirstType FirstType getfirst() getfirst() return return this.first; this.first; SecondType SecondType getsecond() getsecond() return return this.second; this.second; 16:54

Sama Scalalla edellisten kalvojen asiat toimivat samalla lailla Scalassakin syntaksiero: Javassa <>, Scalassa [ ] Aiempi ArrayList-esimerkki Scalalla import scala.collection.mutable.arraybuffer val sanalista ArrayBuffer[String] // tai: val sanalista: ArrayBuffer[String] ArrayBuffer sanalista + "Hei vaan!" sanalista ++ List("foo", "bar") val sana sanalista(0) // tai funktionaalisesti (konstruktorissa ei :tä eikä tarvita tyyppiä): val s1 Vector() // tai Vector[String]() tai List() val s2 s1 :+ "Hei vaan" val s3 s2 ++ List("foo", "bar") val sana s3(0) Aiempi Pair-esimerkki Scalalla class Pair[A, B](first: A, second: B) def getfirst(): A first // (Scala tekee vastaavat metodit def getsecond(): B second // automaattisestikin) Pair(1, "foo").getsecond() "foo"

Ongelma... import import java.util.arraylist; java.util.arraylist; class class PersonnelGroup PersonnelGroup <JobType> <JobType> private private ArrayList<JobType> ArrayList<JobType> people; people; PersonnelGroup() PersonnelGroup() this.people this.people ArrayList<JobType>(); ArrayList<JobType>(); addperson( addperson( JobType JobType Employee Employee ) ) people.add( people.add( Employee Employee ); ); printallnames() printallnames() for for (JobType (JobType person person : : people) people) System.out.println( System.out.println( person.getname() person.getname() ); ); 16:54

Ongelma... import import java.util.arraylist; java.util.arraylist; class class PersonnelGroup PersonnelGroup <JobType> <JobType> private private ArrayList<JobType> ArrayList<JobType> people; people; PersonnelGroup() PersonnelGroup() this.people this.people ArrayList<JobType>(); ArrayList<JobType>(); addperson( addperson( JobType JobType Employee Employee ) ) people.add( people.add( Employee Employee ); ); Ei toimi. Mistä tiedettäisiin että printallnames() printallnames() JobTypellä on metodi for for (JobType (JobType person person : : people) people) getname? System.out.println( System.out.println( person.getname() person.getname() ); ); 16:54

Geneerinen Luokka Tyyppiparametrille voi myös määrätä vaatimuksia <Tyyppi extends Tulostettava> Tyyppiparametriksi Tyyppi saa antaa vain : rajapinnan Tulostettava täyttäviä luokkia tai luokan Tulostettava aliluokkia <Tyyppi extends Tulostettava & Tallennettava> Tyyppiparametriksi Tyyppi saa antaa vain molemmat ehdot täyttäviä tyyppejä Tämä mahdollistaa rajoitteen määrittämien metodien kutsumisen Tyyppiparametrin tyyppisille olioille 16:54

import import java.util.arraylist; java.util.arraylist; class class PersonnelGroup PersonnelGroup <JobType <JobType extends extends BasicEmployee> BasicEmployee> private private ArrayList<JobType> ArrayList<JobType> people; people; PersonnelGroup() PersonnelGroup() this.people this.people ArrayList<JobType>(); ArrayList<JobType>(); printallnames() printallnames() for for (JobType (JobType person person : : people) people) System.out.println( System.out.println( person.getname() person.getname() ); ); addperson( addperson( JobType JobType Employee class BasicEmployee Employee ) ) class BasicEmployee private String name; people.add( people.add( Employee Employee ); private String name; ); BasicEmployee(String name) BasicEmployee(String name) this.name name; this.name name; String getname() String getname() return this.name; return this.name; 16:54

Geneerinen metodi Myös metodimäärittely voi olla geneerinen (riippumatta luokan geneerisyydestä) Tyyppiparametri esitellään puumerkissä ennen paluuarvon tyyppiä static <Tyyppi> ArrayList<Tyyppi> jokatoinen( Tyyppi[] taulu ) static <Tyyppi> ArrayList<Tyyppi> jokatoinen( Tyyppi[] taulu ) ArrayList<Tyyppi> uusitaulu ArrayList<Tyyppi>(); ArrayList<Tyyppi> uusitaulu ArrayList<Tyyppi>(); for (int i 0; i < taulu.length / 2; i++) for (int i 0; i < taulu.length / 2; i++) uusitaulu.add(taulu[i * 2]); uusitaulu.add(taulu[i * 2]); return uusitaulu; return uusitaulu; Metodia kutsuessa tyyppiparametria ei kuitenkaan erikseen anneta (kuten geneeristen luokkien kanssa) vaan se päätellään metodin parametrien tyypeistä 16:54 String[] taulukko Aa, Bb, Cc, Dd, Ee ; String[] taulukko Aa, Bb, Cc, Dd, Ee ; ArrayList<String> lista jokatoinen(taulukko); ArrayList<String> lista jokatoinen(taulukko);

Sama Scalalla Scalassakin tyyppiparametreja voi rajoittaa syntaksi on [A <: B] eikä <A extends B> myös geneeriset metodit toimivat Scalassa samaan tapaan kuin Javassa: tyyppiparametrit kerrotaan ennen parametrilistaa Aiempi jokatoinen-esimerkki Scalalla import scala.collection.mutable.arraybuffer def jokatoinen[a](taulu: Array[A]): ArrayBuffer[A] val uusi ArrayBuffer[A] for (i <- Range(0, taulu.length/2)) uusi + taulu(i*2) uusi jokatoinen(array(6,5,4,3,2,1)) ArrayBuffer(6,4,2) // tai Scala-maisemmin eli funktionaalisesti: def everyother[a](l: Seq[A]) l.indices.by(2).map l(_) everyother(array(6,5,4,3,2,1)) Vector(6,4,2) everyother(list(6,5,4,3,2,1)) Vector(6,4,2) everyother(arraybuffer(6,5,4,3,2,1)) Vector(6,4,2)

Sisältö 1 Generics Javassa ja Scalassa 2 Generics-yksityiskohtia 3 Taustaa geneerisistä tyypeistä

Mitä tyyppiparametrilla ei voi tehdä? Tyyppiparametrilla ei voi suoraan luoda olioita tai taulukoita Esim. edellisessä esimerkissä palautettiin lista olioita joiden tyyppi seurasi suoraan tyyppiparametrista. Vastaavaa taulukkoversiota ei olisi voinut tehdä seuraavasti : static <Tyyppi> Tyyppi[] jokatoinen( Tyyppi[] taulu ) static <Tyyppi> Tyyppi[] jokatoinen( Tyyppi[] taulu ) Tyyppi[] uusitaulu Tyyppi[ taulu.length / 2 ]; Tyyppi[] uusitaulu Tyyppi[ taulu.length / 2 ]; Jos tällainen tyyppiparametrin tyyppisen taulukon palauttava metodi olisi haluttu tehdä, joudutaan käyttämään Java:n reflection API:a ja luomaan tarvittavat oliot hieman hankalammin. (reflektiolla on lisäksi myös muita vaikutuksia) static <Tyyppi> Tyyppi[] jokatoinen2( Tyyppi[] taulu ) static <Tyyppi> Tyyppi[] jokatoinen2( Tyyppi[] taulu ) Tyyppi[] uusitaulu Tyyppi[] uusitaulu (Tyyppi[]) java.lang.reflect.array.instance( // Tämä tyyppipakotus (Tyyppi[]) java.lang.reflect.array.instance( // Tämä tyyppipakotus taulu.getclass().getcomponenttype(), // aiheuttaa warningin, taulu.getclass().getcomponenttype(), // aiheuttaa warningin, taulu.length / 2); // mutta koodissa ei ole taulu.length / 2); // mutta koodissa ei ole // virhettä // virhettä for (int i 0; i < taulu.length / 2; i++) for (int i 0; i < taulu.length / 2; i++) uusitaulu[ i ] taulu[ i * 2 ]; uusitaulu[ i ] taulu[ i * 2 ]; return uusitaulu; return uusitaulu; 16:54

Scalan tapa korjata edellinen rajoitus se, ettei taulukoita voi tehdä tyyppiparametrista, johtuu Javan taulukkotyypin rajoituksista muilla tyypeillä (kuten ArrayList ja Scalan ArrayBuffer edellä) ongelmaa ei ole Scalassa myös Java-taulukoita Array voi tehdä tyyppiparametrista mutta kääntäjää auttamaan tarvitaan ylimääräinen yksityiskohta tämä liittyy Java-virtuaalikoneen geneeristen tyyppien puutteisiin tyyppiparametrin syntaksi : ClassManifest lisää funktiolle ylimääräisen piilotetun (implicit) argumentin, joka välittää puuttuvan tyyppi-informaation uusia tyyppiparametrin mukaisia olioita ei Scalassakaan voi luoda Esimerkki mistä kääntäjä tietäisi konstruktorin argumenttien tyypit? def jokatoinen[a : ClassManifest](taulu: Array[A]): Array[A] val uusi Array[A](taulu.length/2) for (i <- Range(0, taulu.length/2)) uusi(i) taulu(i*2) uusi

Vaatimuksia tyyppiparametrin arvolle java.util.comparable-rajapinnan avulla voi tehdä paljon alkioiden järjestykseen liittyvää (järjestämistä, hakuja, jne) Rajapinta on yksinkertainen sen täyttävä luokka lupaa hyväksyä compare-metodin parametriksi annetun tyyppiparametrin tyyppisiä olioita. interface interface Comparable Comparable <T> <T> int int compareto(t compareto(t other); other); Voidaan siis toteuttaa luokka OmaLuku: class class Omaluku Omaluku implements implements Comparable Comparable <Omaluku> <Omaluku> int int compareto(omaluku compareto(omaluku other) other)...jotain...jotain Näin määriteltynä OmaLuku-luokan olioita aan siis verrata 16:54 toisiin luokan OmaLuku olioihin.

Vaatimuksia tyyppiparametrin arvolle OmaLuku olisi voinut kuitenkin täyttää jonkin muun rajapinnan, vaikka Comparable<String> jolloin sen olioita olisi pitänyt a verrata merkkijonoihin. (ei ehkä niin kovin hyödyllistä) esim. Järjestämisalgoritmeille on olennaista että olioita aan verrata toisiin saman luokan olioihin. Tällainenkin vaatimus aan kirjoittaa Vaatimukset tyypille tulevat vasta luokan olioita käyttävältä koodilta, vaikkapa järjestämismetodilta. (allaoleva metodimäärittely luokassa Collections) <T <T extends extends Comparable<T>> Comparable<T>> sort(list<t> sort(list<t> list) list)...eli sort-metodi suostuu ottamaan listoja joiden alkiot ovat verrattavissa itseensä. Edellisen kalvon OmaLuku-luokka täyttää tämän vaatimuksen joten järjestäminen onnistuu helposti ArrayList<Omaluku> ArrayList<Omaluku> lista lista............ java.util.collections.sort(lista); java.util.collections.sort(lista); // // Järjestää Järjestää listan listan alkiot alkiot // // compare-metodia compare-metodia käyttäen. käyttäen. 16:54

Sama Scalassa vaatimukset tyyppiparametreille toimivat Scalassa kuten Javassa syntaksi esim. def f[a <: Foo[A]](x: A) x Scalan vastineet Comparablelle ovat Ordered ja Ordering Ordered on lähempi vastine, mutta Ordering suositeltavampi: Orderingilla voi määritellä samalle luokalle useamman järjestyksen Esimerkki oman luokan järjestyksen määrittelemisestä case class MyPair[A <% Ordered[A], B <% Ordered[B]](first: A, second: B) extends Ordered[MyPair[A,B]] def compare(that: MyPair[A, B]): Int val f this.first.compare(that.first) if (f 0) this.second.compare(that.second) else f MyPair(1,"foo") < MyPair(1,"bar") false esimerkissä oleva <% eli view bound on kuten <:, mutta kelpuuttaa myös tyypit, jotka voi implisiittisesti muuntaa Ordered[A]-rajapinnan toteuttavaksi tyypiksi käytännössä primitiivityypit, esim. Int ja String, ovat tällaisia

WildCard List<?> List<?> lista; lista; lista lista ArrayList<String>(); ArrayList<String>(); lista lista ArrayList<Integer>(); ArrayList<Integer>(); lista lista ArrayList<IhanMikaVaanTyyppi>(); ArrayList<IhanMikaVaanTyyppi>(); Wildcard? Tässä? on ns. wildcard tyyppiparametri, jota ei nimetä Sen avulla voi tehdä mm. ylläolevan viittauksen listaan jonka alkiot voivat olla mitä tahansa tyyppiä. Ikävä kyllä List<?> listaan ei voi lisätä mikään tyyppisiä alkioita Listan alkioiden tyyppi ei ole tiedossa joten mitään metodia jonka parametrin tyyppi on tyyppiparametrin määrittämä ei voi kutsua. Alkioiden hakukin on vähän hankalampaa Esim get:in paluuarvon tyyppiä ei tiedetä, joten alkioita voi sijoittaa vain Object-tyyppisiin muuttujiin ilman tyyppipakotusta. 16:54

WildCard tallennalistaan( tallennalistaan( List List <? <? super super String> String> lista, lista, String String alkio) alkio) super : Wildcard tulee hyödyllisemmäksi kun sitä rajoitetaan Ylläolevan metodin parametrina on lista johon voi tallentaa merkkijonoja sekä String:in yliluokan (Object) olioita. Käytännössä siis mikä tahansa lista johon aan varmasti tallentaa merkkijonoja. (String:inhän saa tallentaa Object-tyyppiseen muuttujaan) super-määre toimii vain wildcardeille. Sen yhteydessä ei voi käyttää tyyppiparametria tyyliin Tyyppi super String extends : Aiemmin nähty extends toimii myös wildcardeille tulostalista( List <? extends Tulostettava> lista) Lista josta otettavat alkiot ovat Tulostettava-luokan/rajapinnan instansseja kaannalista( List<?> kaannatama) Rajoittamaton wildcard - Lista mitä vain tyyppiä Käytännössä (lähes) sama kuin List<? extends Object> 16:54

Entä Scala-vastineet? Javan?:n vastine Scalassa on _ esim. def f(a: List[_]) a Javan tyyppien super:n vastine on >: (vrt. <: eli extends) mutta Scalassa kannattaa wildcardin sijasta usein tehdä tyyppiparametrin varianssiannotaatio + tai - class Stack1[A]... class Stack2[+A]... class Stack3[-A]... Stack1[String]:llä ja Stack1[Object]:lla ei ole alityyppisuhdetta (alityypitys on A:n suhteen invarianttia) Stack2[String] <: Stack2[Object], sillä String <: Object (kovarianttia) Stack3[Object] <: Stack3[String] (kontravarianttia) lisätietoja: SbE 8.2 näitä tarvinnee käytännössä melko harvoin...

Sisältö 1 Generics Javassa ja Scalassa 2 Generics-yksityiskohtia 3 Taustaa geneerisistä tyypeistä

Java-ongelma: tyyppien poistaminen käännetyssä Javan tavukoodissa ei ole tietoa tyyppiparametreista tieto poistetaan käännösaikana (type erasure) samalla Java-kääntäjä tuottaa tavukoodiin ylimääräisiä tyyppipakotuksia tyyppiparametreja käytettäessä Java-virtuaalikone vaatii pakotuksen aiheuttaman ajonaikaisen tyyppitarkistuksen, vaikka kääntäjä tietää että se aina onnistuu joskus ongelma näkyy koodissakin: esim. instanceof ei pysty tunnistamaan tyyppiparametria pohjimmiltaan ongelma johtuu siitä, että geneeristen tyyppien tuki lisättiin vasta Java 5:een eli kieleen, jossa ei aiemmin ollut tukea niille samasta syystä Javan taulukoissa on edellä mainittuja rajoituksia (ne ovat peräisin aiemmista Javan versioista) Java 5 halusi olla yhteensopiva aiempien virtuaalikoneiden kanssa (mutta tämä ei kuitenkaan muista syistä lopulta toteutunut) Scalassa on enimmäkseen sama ongelma (sama virtuaalikone) lisätietoja: http://lamp.epfl.ch/~emir/bqbase/2006/10/16/erasure.html

Geneeristen tyyppien toteuttamisesta miten geneerisiä tyyppejä käyttävä koodi ajon aikana toimii? kaksi perusratkaisua: 1 geneerisestä luokasta ja metodista on vain yksi toteutus: koodi ottaa ajon aikana tarvittaessa selville, mitä konkreettisia tyyppejä se käsittelee (mm. Java, Scala) 2 käännetään etukäteen oma koodi jokaiselle ohjelmassa käytetylle tyyppiparametrin arvolle (mm. C++) jälkimmäisellä tavalla koodista saadaan tehokkaampaa, koska se tietää tarkat tyypit ja voi erikoistua (specialize) niihin erityisesti primitiivityyppejä (ei-oliot) käytettäessä mutta käännetty koodi pitenee, sillä siinä on useita kopioita samoista metodeista ensimmäistä aan optimoida: ajon aikainen kääntäjä (JIT) voi tehdä erikoistuneita versioita metodeista huomatessaan, että niitä käytetään paljon ohjelmoija voi pyytää kääntäjää kääntämään tietyt erikoistuneet versiot etukäteen (esim. Scala 2.8:n @specialized)

Parametrinen polymorsmi parametrinen polymorsmi on käsite, jonka mukaan funktio voi toimia eri tavalla riippuen tyyppiparametreistaan funktiolla on monta muotoa, ja kutsussa (usein implisiittisesti) annettu tyyppiparametri kertoo, mitä muotoa nyt käytetään käytännössä muodot eroavat vain niiltä kohdin, joissa tyyppiparametrien tyyppisiä arvoja käsitellään perinnän tuottama monimuotoisuus on vastaavasti alityyppipolymorsmia tai ad-hoc-polymorsmia (termien käyttö vaihtelee) aliluokan olio kelpaa yliluokan olion tilalle esim. metodi, joka ottaa argumentiksi yliluokan olion, voi muuntua käsittelemään myös aliluokan oliota generics on olio-ohjelmointikielten nimitys ja toteutus parametriselle polymorsmille

Parametrinen polymorsmi ilman olioita muissa kuin oliokielissä parametrinen polymorsmi on yleensä helpompaa ymmärtää ja eri kielissä enimmäkseen samanlaista (toisin kuin esim. moniperintä oliokielissä) vähemmän monimutkaisia yksityiskohtia se on hyvin yleisessä käytössä esim. Haskellissa ja ML:ssä näissä geneerisiä tyyppejä käytetään vielä enemmän kuin Javassa ja Scalassa tyyppipäättelijä tekee niistä ohjelmoijalle näkymättömämpiä monet genericsien monimutkaisuudet liittyvät parametrisen polymorsmin yhdistämiseen olioihin ja perintään eräs ohjelmointikielten teorian pitkäaikainen ongelma on ollut keksiä siisti tapa yhdistää parametrinen ja alityyppipolymorsmi tosin osa ongelmasta on ollut siinä, että perinnän toteutus ei ole yhtä vakiintunutta kuin parametrisen polymorsmin tutkimus jatkuu: Scalankaan ratkaisu ei liene viimeinen...