Typy uogólnione. Robert A. Kªopotek Wydziaª Matematyczno-Przyrodniczy. Szkoªa Nauk cisªych, UKSW

Podobne dokumenty
TYPY GENERYCZNE (GENERICS)

Metody sparametryzowane

Polimorfizm a klasy generyczne w języku Java. Zdzisław Spławski 1

Kurs programowania. Wykład 9. Wojciech Macyna. 28 kwiecień 2016

Aplikacje w Javie wykład 6 Klasy wewnętrzne, klasy anonimowe Typy i metody sparametryzowane (generics)

Aplikacje w środowisku Java- wykład 6 Klasy wewnętrzne, klasy anonimowe Klasy opakowujące Typy i metody sparametryzowane (generics) wildcards

Programowanie obiektowe

Interfejsy, klasy wewn trzne jako szczególny rodzaj obiektów

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Kurs programowania. Wykład 9. Wojciech Macyna

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object

Programowanie obiektowe

Polimorfizm, metody wirtualne i klasy abstrakcyjne

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Kolekcje obiektów. Wyj tki.

Enkapsulacja, dziedziczenie, polimorfizm

Kompozycja i dziedziczenie klas

Typy uogólnione. Programowanie obiektowe. Jacek Sroka na podstawie materiałów Janusza Jabłonowskiego. 8 kwietnia 2013

Programowanie obiektowe

Aplikacje w środowisku Java

Podstawy otwartych języków programowania Przechowywanie danych

Dokumentacja do API Javy.

Interfejsy. Programowanie obiektowe. Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej

Programowanie obiektowe

Klasy generyczne. ZbiórLiczb. ZbiórCzegokolwiek. Zbiór

Typy sparametryzowane

Imi i nazwisko... Egzamin - Programowanie Obiektowe II rok informatyki, studia pierwszego stopnia, niestacjonarne Termin zerowy

Programowanie obiektowe

1 Atrybuty i metody klasowe

dr inż. Piotr Czapiewski Tworzenie aplikacji w języku Java Laboratorium 1

Realizacja ekstensji klasy. Paulina Strzelecka, Tomasz Roszkowski

Programowanie obiektowe

Programowanie obiektowe

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Wzorce projektowe strukturalne cz. 1

Programowanie Komputerów

Aplikacje Internetowe. Najprostsza aplikacja. Komponenty Javy. Podstawy języka Java

Dziedziczenie. dr Jarosław Skaruz

Model obiektu w JavaScript

Na przykładzie języków Java, C# i odrobiny C++ Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Kurs programowania. Wstęp - wykład 0. Wojciech Macyna. 22 lutego 2016

Wykład 2 Wybrane konstrukcje obiektowych języków programowania (1)

Podstawy i języki programowania

import java.util.*; public class ListExample { public static void main(string args[]) { List<String> lista1= new ArrayList<String> ();

Dawid Gierszewski Adam Hanasko

1. Klasa typu sealed. Przykład 1. sealed class Standard{ class NowyStandard:Standard{ // błd!!!

Język JAVA podstawy. Wykład 4, część 3. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

WSNHiD, Programowanie 2 Lab. 2 Język Java struktura programu, dziedziczenie, abstrakcja, polimorfizm, interfejsy

Przykład -

PHP 5 język obiektowy

Język JAVA podstawy. Wykład 4, część 1. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Java: interfejsy i klasy wewnętrzne

Programowanie obiektowe w C++ Wykªad 4

Programowanie w Javie 1 Wykład i Ćwiczenia 3 Programowanie obiektowe w Javie cd. Płock, 16 października 2013 r.

Platformy Programistyczne Podstawy języka Java

Kurs programowania. Wykład 13. Wojciech Macyna. 14 czerwiec 2017

Kurs programowania. Wykład 3. Wojciech Macyna. 22 marca 2019

Klasy abstrakcyjne, interfejsy i polimorfizm

Polimorfizm. dr Jarosław Skaruz

Java podstawy jęyka. Wykład 2. Klasy abstrakcyjne, Interfejsy, Klasy wewnętrzne, Anonimowe klasy wewnętrzne.

Laboratorium 03: Podstawowe konstrukcje w języku Java [2h]

Szablony funkcji i klas (templates)

Programowanie obiektowe i zdarzeniowe

1 Stos: Stack i Stack<T>

Programowanie w języku Java. Kolekcje

Języki i techniki programowania Ćwiczenia 3 Dziedziczenie

JAVA. Java jest wszechstronnym językiem programowania, zorientowanym. apletów oraz samodzielnych aplikacji.

Podstawy Języka Java

Programowanie w Javie - wykład 3

Wykład 4: Klasy i Metody

PARADYGMATY PROGRAMOWANIA Wykład 4

Technologie i usługi internetowe cz. 2

Na przykładzie języków Java, C# i odrobiny C++ Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

UML a kod w C++ i Javie. Przypadki użycia. Diagramy klas. Klasy użytkowników i wykorzystywane funkcje. Związki pomiędzy przypadkami.

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Programowanie Obiektowe (Java)

Programowanie 2. Język C++. Wykład 3.

0.1 Hierarchia klas Diagram Krótkie wyjaśnienie

Wykład 7: Pakiety i Interfejsy

Programowanie w języku Java

Zaawansowane programowanie w języku C++ Funkcje uogólnione - wzorce

Programowanie obiektowe

Programowanie w środowiskach graficznych. Wykład 3 Język C#

Wykład 2: Podstawy Języka

Programowanie obiektowe

1 Klasy. 1.1 Denicja klasy. 1.2 Skªadniki klasy.

Definicje klas i obiektów. Tomasz Borzyszkowski

Programowanie obiektowe

Podstawowe części projektu w Javie

Programowanie obiektowe

Wywoływanie metod zdalnych

Wprowadzenie do szablonów szablony funkcji

Metody Metody, parametry, zwracanie wartości

Programowanie w Javie - wykład 4

Projektowanie obiektowe oprogramowania Wykład 4 wzorce projektowe cz.i. wzorce podstawowe i kreacyjne Wiktor Zychla 2015

Programowanie w Internecie. Java

Java niezbędnik programisty spotkanie nr 9. Java 2 Platform, Standard Edition 5.0

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

1. Co można powiedzieć o poniższym kodzie (zakładając, że zaimportowano wszystkie niezbędne klasy)?

Transkrypt:

Typy uogólnione. Robert A. Kªopotek r.klopotek@uksw.edu.pl Wydziaª Matematyczno-Przyrodniczy. Szkoªa Nauk cisªych, UKSW 23.03.2017

Typy uogólnione (1/2) Typy uogólnione (generyczne) s to typy parametryzowane typem Ich wªasno±ci w j zyku Java w znacz cy sposób odbiegaj od koncepcji szablonów znanej z C++, pomimo podobie«stwa zapisu. S dost pne od Java 1.5 Na typach generycznych opiera si implementacja biblioteki kolekcji (kontenerów) j zyka Java, biblioteka java.util W Java 8 wprowadzono nast puj ce modykacje: Optymalizacja wspóªbie»no±ci kolekcji Otwarcie kolekcji na wyra»enia lambda 2 / 32

Typy uogólnione (2/2) Typy generyczne nie s zgodne z klasowo-obiektowym paradygmatem programowania Stanowi wi c rozszerzenie pierwotnych mo»liwo±ci j zyka Java Wspieraj one paradygmat uogólniony nazywamy paradygmatem generycznym Zalety: kontrola typów na poziomie kompilacji, a nie dopiero w trakcie dziaªania programu brak potrzeby rzutowania konstruowanie ogólnych algorytmów 3 / 32

Koncepcja typów uogólnionych w Java Do± wysoki stopie«uogólniania kodu byª i jest w Javie dost pny poprzez: zagwarantowane dziedziczenie klasy Object implementacj interfejsów mechanizmy reeksji (czyli np. dynamiczne, w fazie wykonania programu, odwoªania do pól i metod klas) wprowadzenie generics (typów uogólnionych) dodaje uªatwienia w postaci unikania konwersji zaw»aj cych tworzenia bardziej czytelnego kodu wykrywania bª dów w fazie kompilacji i unikania wyj tku ClassCastException 4 / 32

Zalety typów uogólnionych w kolekcjach (1/2) bezpiecze«stwo typów - mo»emy przetrzymywa obiekty tylko jednego typu rzutowanie typów nie jest konieczne bez typów generycznych List list = new ArrayList (); list. add (" hello " ); String s = ( String ) list. get (0); // rzutowanie z typami uogólnionymi List < String > list = new ArrayList < String >(); list. add (" hello " ); String s = list. get (0); 5 / 32

Zalety typów uogólnionych w kolekcjach (2/2) sprawdzanie w momencie kompilacji - problemy z przetrzymywanie obiektów niewªa±ciwych typów nie pojawi si podczas dziaªania List < String > list = new ArrayList < String >(); list. add (" hello " ); list. add (32); // Bª d kompilacji! 6 / 32

Typy parametrów - konwencja oznacze«t - Type E - Element K - Key N - Number V - Value 7 / 32

Ogólna klasa reprezentuj c dowolne pary (1/2) class ParaObj { Object first ; Object last ; public ParaObj ( Object f, Object l) { first = f; last = l; public Object getfirst () { return first ; public Object getlast () { return last ; public void setfirst ( Object f) { first = f; public void setlast ( Object l) { last = l; 8 / 32

Ogólna klasa reprezentuj c dowolne pary (2/2) ParaObj po = new ParaObj (" Ala ", new Integer (3)); System. out. println ( po. getfirst () + " " + po. getlast ()); // Problem 1 // konieczne konwersje zaw»aj ce String name = ( String ) po. getfirst (); int nr = ( Integer ) po. getlast (); po. setfirst ( name + " Kowalska " ); po. setlast ( new Integer ( nr + 1)); System. out. println ( po. getfirst () + " " + po. getlast ()); // Problem 2 // mo»liwe bª dy po. setlast (" kot " ); System. out. println ( po. getfirst () + " " + po. getlast ()); // Bª d mo»e by wykryty w fazie wykonania // pó¹no, czasem w innym module Integer n = ( Integer ) po. getlast (); // ClassCastException 9 / 32

Para - typ uogólniony (1/3) class Para <S, T> { S first ; T last ; public Para ( S f, T l) { first = f; last = l; public S getfirst () { return first ; public T getlast () { return last ; public void setfirst ( S f) { first = f; public void setlast ( T l) { last = l; 10 / 32

Para - typ uogólniony (2/3) Para < String, String > p1 = new Para < String, String > (" Jan ", " Kowalski " ); Para < String, Data > p2 = new Para < String, Data > (" Jan Kowalski ", new Date ()); Para < Integer, Integer > p = new Para < Integer, Integer >(1,2); // autoboxing dziaªa ; // autoboxing Para < String, Integer > pg = new Para < String, Integer >( " Ala ", 3); System. out. println ( pg. getfirst () + " " + pg. getlast ()); String nam = pg. getfirst (); // bez konwersji! int m = pg. getlast (); // bez konwersji! pg. setfirst ( name + " Kowalska " ); pg. setlast ( m +1); // autoboxing System. out. println ( pg. getfirst () + " " + pg. getlast ()); 11 / 32

Para - typ uogólniony (3/3) Para < String, Integer > p1 = new Para < String, Integer >( " Ala ", 3); Para < String, String > p2 = new Para < String, String >( " Ala ", " Kowalska " ); // " Raw Type " Class p1class = p1. getclass (); System. out. println ( p1class ); // class Para Class p2class = p2. getclass (); System. out. println ( p2class ); // class Para // zwraca tablic metod deklarwoanych w klasie Method [] mets = p1class. getdeclaredmethods (); for ( Method m : mets ) System. out. println (m ); // public java. lang. Object Para. getfirst () // public java. lang. Object Para. getlast () // public void Para. setfirst ( java. lang. Object ) // public void Para. setlast ( java. lang. Object ) 12 / 32

Para - podsumowanie jest tylko jedna klasa Para dla wszystkich instancji klasy sparametryzowanej Para<S, T>; typ wyznaczany przez t klas nazywa si typem surowym ("raw type"), z denicji klasy Para znikn ªy wszystkie parametry typu i zostaªy zast pione przez Object; ten mechanizm nazywa si czyszczeniem typów ("type erasure"), poniewa» jest tylko jedna klasa Para - np. zmienne reprezentowane przez pola statyczne s wspólne dla wszystkich instancji typu sparametryzowanego 13 / 32

Mo»emy (w denicjach uogólnionych klas i metod) podawa je jako typy pól i zmiennych lokalnych podawa je jako typy parametrów i wyników metod dokonywa jawnych konwersji do typów oznaczanych przez nie (ale to b dzie tylko wa»ne na etapie kompilacji, po to by unikn bª dów niezgodno±ci typów, natomiast nie uzyskamy w fazie wykonania faktycznych konwersji np. zaw»aj cych) wywoªywa na rzecz zmiennych oznaczanych typami sparametryzowanymi metody klasy Object (i ew. wªa±ciwe dla klas i interfejsów, które stanowi tzw. górne ograniczenia danego parametru typu) 14 / 32

Nie mo»emy (w denicjach uogólnionych klas i metod) (1/2) tworzy obiektów typów sparametryzowanych (new T() jest niedozwolone, no bo na poziomie denicji generics nie wiadomo co to konkretnie jest T) u»ywa operatora instanceof ( z powodu j.w.) u»ywa ich w statycznych kontekstach (bo statyczny kontekst jest jeden dla wszystkich ró»nych instancji typu sparametryzowanego) u»ywa ich w literaªach klasowych wywoªywa metod z konkretnych klas i interfejsów, które nie s zaznaczone jako górne ograniczenia parametru typu (w najprostszym przypadku t górn granic jest Object, wtedy mo»emy u»ywa tylko metod klasy Object) 15 / 32

Nie mo»emy (w denicjach uogólnionych klas i metod) (2/2) u»ywa typów sparametryzowanych przy tworzeniu tablic (podaj c je jako typ elementu tablicy) w obsªudze wyj tków (bo jest to mechanizm fazy wykonania) w literaªach klasowych (bo oznaczaj typy fazy wykonania) 16 / 32

Ograniczenia parametrów typu istnieje mo»liwo± ograniczenia zakresu klas/interfejsów jaki dany typ uogólniony b dzie przyjmowaª sªu»y do tego sªowo extends public class Box <T> { private T t; public void set ( T t) { this.t = t; public <U extends Number > void inspect ( U u ){ System. out. println ("T: " + t. getclass (). getname ()); System. out. println ("U: " + u. getclass (). getname ()); public static void main ( String [] args ) { Box < Integer > integerbox = new Box < Integer >(); integerbox. set ( new Integer (10)); integerbox. inspect (" some text " ); // Bª d kompilacji! 17 / 32

Wielokrotne ograniczenie parametrów typu zapisujemy jako: <T extends B1 & B2 & B3> jesli na li±cie ogranicze«jest klasa to musi by wymieniona jako pierwsza (mo»e by tylko jedna klasa a reszta interfejsy), np: Class A { /*... */ interface B { /*... */ interface C { /*... */ class D <T extends A & B & C > { /*... */ je±li A nie b dzie wymieniona jako pierwsza dostaniemy bª d kompilacji class D <T extends B & A & C > { /*... */ // Bª d kompilacji! 18 / 32

Generyki - dziedziczenie i podtypy w j zyku Java je±li mamy zale»no± klasa Integer dziedziczy po Number to mo»emy na ni rzutowa bez problemów, np: Box < Number > box = new Box < Number >(); box. add ( new Integer (10)); // OK box. add ( new Double (10.1)); // OK problem pojawia si wtedy, je±li chcieliby±my rzutowa na siebie typy generyczne, np. Box<Number> i Box<Integer> 19 / 32

Podtypy - jak to zrobi? (1/2) mo»emy tworzy podtypy oraz hierarchi typów za pomoc rozszerzania klas i interfejsów generycznych jednym z przykªadów jest klasa ArrayList<E> implements List<E> oraz List<E> extends Collection<E> mo»emy wtedy zdeniowa wªasne klasy lub interfejsy generyczne je rozszerzaj ce, np: interface PayloadList <E,P> extends List <E> { void setpayload ( int index, P val );... 20 / 32

Podtypy - jak to zrobi? (2/2) parametryzacje typu PayloadList<E,P> extends List<E>, takie jak PayloadList<String,String> PayloadList<String,Integer> PayloadList<String,Exception> s podtypem List<String> 21 / 32

Parametry uniwersalne (wildcards) Je±li ArrayList<Integer> i ArrayList<String> nie s podtypami ArrayList<Object> - to jak stworzy metod wypisuj c zawarto± dowolnej listy ArrayList? Do tego sªu» parametry uniwersalne (wildcards) - oznaczenie "?" S trzy typy takich parametrów: ograniczone z góry <? extends X> - oznacza "wszystkie podtypy X" ograniczone z doªu <? super X> - oznacza "wszystkie nadtypy X" nieograniczone <?> - oznacza "wszystkie typy" 22 / 32

Wariancja typów uogólnionych Typ sparametryzowany C<T> jest kowariantny wzgl dem parametru T, je±li dla dowolnych typów A i B, takich,»e B jest podtypem A, typ sparametryzowany C<B> jest podtypem C<A> (kowariancja - bo kierunek dziedziczenia typów sparametryzowanych jest zgodny z kierunkiem dziedziczenia parametrów typu) Kowariancj uzyskujemy za pomoc symbolu <? extends X> Przykªad: List<? extends Number> jest nadtypem wszystkich typów sparametryzowanych, gdzie parametrem typu jest Number albo typ pochodny od Number. 23 / 32

Kowariancja typów uogólnionych Typ sparametryzowany C<T> jest kontrawariantny wzgl dem parametru T, je»eli dla dowolnych typów A i B, takich»e B jest podtypem A, typ sparametryzowany C<A> jest podtypem typu sparametryzowanego C<B> (kontra - bo kierunek dziedziczenia jest przeciwny). Kontrawariancj uzyskujemy za pomoc symbolu <? super X>. Przykªad: Integer jest podtypem Number, a List<Number> jest podtypem List<? super Integer>, wobec czego mo»emy podstawia : List<? super Integer> list = new ArrayList<Number>; 24 / 32

Biwariancja typów uogólnionych Biwariancja oznacza równoczesn kowariancj i kontrawariancj typu sparametryzowanego Przykªad: ArrayList<?> jest nadtypem ArrayList<? extends Integer> i nadtypem dla ArrayList<? super Integer> 25 / 32

Metody sparametryzowane i konkludowanie typów Parametryzacji mog podlega nie tylko klasy czy interfejsy, ale równie» metody. Denicja metody sparametryzowanej ma posta : specyfikatordost pu [ static ] < ParametryTypu > typwyniku nazwa ( lista parametrów ) { //... Argumenty typów s okre±lane na podstawie faktycznych typów u»ytych przy wywoªaniu metody Proces wyznaczania aktualnych argumentów typów nazywa si konkludowaniem typów (ang. type inferring) 26 / 32

Konkludowanie typów - przykªad public class Metoda { public static <T extends Comparable <T>> T max ( T [] arr ) { T max = arr [0]; for ( int i =1; i < arr. length ; i ++) if ( arr [i ]. compareto ( max ) > 0) max = arr [i ]; return max ; public static void main ( String [] args ) { Integer [] ia = { 1, 2, 77 ; int imax = max ( ia ); // w wyniku konkluzji T staje si Integer Double [] da = {1.5, 231.7 ; double dmax = max ( da ); // w wyniku konkluzji T staje si Double System. out. println ( imax + " " + dmax ); 27 / 32

Konikty typów uogólnionych - przykªad (1/4) Mamy struktur : class Person, class VipPerson extends Person oraz class SuperPerson extends VipPerson static void addpersontolist ( List < Person > list ) { list. add ( new Person (" Arek " )); // ok list. add ( new VipPerson (" Arek ", 1)); // ok static void addanytolist ( List list ) { list. add ( new Person (" Arek " )); // ok list. add ( new VipPerson (" Arek ", 1)); // ok list. add ( new Integer (1)); // ok static void printlist ( List list ) { // dowolna lista System. out. println ( list. tostring ()); 28 / 32

Konikty typów uogólnionych - przykªad (2/4) void printfromlist ( List <? extends Person > list ) { Person person = list. get (0); System. out. println ( person ); void addpersontolist2 ( List <? extends Person > list ) { list. add ( new Person (" Arek " )); // -> // bª d bo nie wiadomo czy to lista // VipPerson, Person, czy jaka± inna klasa dziedzicz ca po Pers list. add ( new VipPerson (" Arek ", 1)); // te» bª d void addpersontolist3 ( List <? super VipPerson > list ) { list. add ( new Person (" Arek " )); // -> // bª d. Co je±li jest to List < VipPerson >? // Wtedy nie mo»na doda Person list. add ( new VipPerson (" Arek ", 1)); // ok list. add ( new SuperPerson (" Arek " )); // ok list. add ( new Object ()); // bª d Object object = list. get (0); // typ Object. Nie wiemy jakiego typu jest // obiekt w li±cie. Mo»e VipPerson, mo»e // Person... kto wie!? 29 / 32

Konikty typów uogólnionych - przykªad (3/4) void addpersontolist4 ( List <? super Person > list ) { list. add ( new Person (" Arek " )); // ok list. add ( new VipPerson (" Arek ", 1)); // ok Object object = list. get (0); // tylko object, bo w sumie nie wiadomo jakiego jest typu public static void copy ( List <? extends VipPerson > src, List <? super VipPerson > dest ) { for ( int i = 0; i < src. size (); i ++) dest. add ( src. get (i )); 30 / 32

Konikty typów uogólnionych - przykªad (4/4) public static void main ( String [] args ) { List < Person > list = new ArrayList < >(); addpersontolist ( list ); // sposoby deklaracji List < Person > peoplelist = new ArrayList < >(); // ok List < Person > list3 = new ArrayList < Person >(); // ok List < Person > list2 = new ArrayList < VipPerson >(); // bª d addanytolist ( peoplelist ); // ok List < VipPerson > viplist = new ArrayList < >(); // ok addpersontolist ( viplist ); // -> // bª d ( nie ka»dy Person jest VipPerson ) List < SuperPerson > superlist = new ArrayList < >(); // ok copy ( superlist, peoplelist ); // ok 31 / 32

32 / 32 Pytania?