9. Kapitel GENERICS. Techniken der Programmentwicklung Prof. Dr. Wolfgang Schramm

9.  Kapitel   GENERICS       Techniken  der  Programmentwicklung   Prof.  Dr.  Wolfgang  Schramm   Übersicht   1   1.  Programmstrukturierung  ...
Author: Dominik Richter
11 downloads 3 Views 3MB Size
9.  Kapitel  

GENERICS  

   

Techniken  der  Programmentwicklung   Prof.  Dr.  Wolfgang  Schramm  

Übersicht   1  

1.  Programmstrukturierung  mit   Paketen  (packages)   2.  Vererbung   3.  Abstrakte  Klassen  und  Interfaces   4.  Ausnahmebehandlung   5.  Datenströme:  die  Java  IO-­‐Bibliothek   6.  MulSthreading   7.  CollecSons   8.  Innere  Klassen   9.  Generics   10.  ReflecSon  

Lernziele  des  Kapitels   2  

¨ 

¨ 

¨ 

¨ 

Verstehen  warum  man  (in  Java  5)   Generics  eingeführt  hat.   Kennenlernen  des  Generic-­‐ Konzepts.   Verstehen,  was  generisch  sein   kann.   Selbst  generische  Klassen  und   Methoden  schreiben  können.  

Inhalt   3  

1.  Einführung  /  MoSvaSon   2.  Generics  (DefiniSon)   3.  Generische  Klassen   •  • 

Subtyping   Wildcards  

4.  Generische  Methoden   5.  Anwendungsbeispiele  

Beispiel:  Einfacher  Stack  für  besSmmte  Objekte   5  

Stack für String-Objekte

Stack für Integer-Objekte

Schlecht: 2 x quasi derselbe Code für dieselben Aufgaben. Frage: Kann man das mit unserem Wissen nicht besser machen? Wenn ja: Wie?

Beispiel:  Einfacher  Stack  für  alle  Arten  von  Objekten   6  

Laufzeitfehler

ADT  Stack:  Problem  Typsicherheit   7  

o  o  o 

o 

o 

o 

o 

Der  ADT  Stack  ist  prinzipiell  offen  für  jeden  Typ.   Man  speichert  Objekte  vom  allgemeinsten  Typ  Object.   Beim  Lesen  vom  Stack  (pop)  werden  diese  allgemeinen  Objekte   auch  wieder  zurück  geliefert.   Wenn  man  in  einem  Stack  Integer-­‐Objekte  speichert,  will  man  dort   keine  String-­‐Objekte  speichern    –  doch  mit  einen  allgemeinen  Typ   Object  kann  das  nicht  verhindert  werden.   Abhilfe  seit  Java  5  :  die  Nutzung  von  Generics  à  bessere   Typsicherheit,  denn  nur  ganz  spezielle  Objekte  kommen  in  die   Datenstruktur.   Mit  den  Generics  lässt  sich  bei  der  KonstrukSon  des  ADT  Stack   angeben,  welche  Objekte  in  den  Stack  aufgenommen  werden   dürfen.   Dann  ist  man  auch  sicher,  welche  Objekte  man  vom  Stack  zurück   bekommt.  

MoSvaSon   8  

o  o 

o  o 

Wie  abstrahiere  ich  vom  konkreten  Typ  eines  Objekts?   Wie  kann  ich  (typsichere)  Containerklassen  (z.B.  einen  ADT   Stack)  bauen,  die  jedes  beliebige  Objekt  aufnehmen  können?   Wie  baue  ich  typsichere  Frameworks?   Wie  vermeide  ich  (unsichere)  Casts  und  mache  dadurch   meinen  Code  typsicher?  

Beispiel:  Stack  mit  Generics   9  

Beispiel:  Stack  mit  Generics   10  

Compilezeitfehler

Generische  Typen  –  Warum?   11  

o 

¨ 

o 

Bei  den  ersten  getypten  Programmiersprachen  (z.B.  Pascal):   ⇒  Programmierer  musste  dieselbe  Datenstruktur  für  jeden   Datentyp,  der  unterstützt  wurde,  definieren.   ⇒  Eine  Liste  von  Zahlen,  eine  Liste  von  Zeichen  und  eine  Liste   von  Datumsangaben  wird  (im  Grunde)  auf  dieselbe  Weise   programmiert.  Die  Algorithmen  zum  Einfügen,  Suchen  und   Löschen  laufen  stets  gleich  ab.   Wünschenswert:  die  ImplemenSerung  der  Liste  unabhängig  von   diesen  Typen  vorzunehmen.   Erster  Verbesserungsansatz  in  Java  durch  Vererbungsbeziehung     ⇒  Ziel  nur  teilweise  erreicht  à  keine  Unterstützung  bezüglich   der  Typüberprüfungen  zur  Compilezeit.  

Generische  Typen  in  Java   12  

o 

o 

o 

Ein  generischer  Typ  à  Erzeugung  von  Datentypen,  die  von   den  zu  Grunde  liegenden  Typen  abstrahieren.     CharakterisSsch  für  generischen  Programmierung  à  die   Algorithmen  werden  nicht  für  einen  besSmmten  Datentyp   geschrieben.  Sie  stellen  nur  besSmmte  Anforderungen  an  die   Typen.   Generische  Typen  in  der  InformaSk:  Datentypen  mit  der   Möglichkeit  zur  Angabe  von  Typparametern.  

Generische  Programmierung  –  Was  ist  das?   13  

o  o  o 

o 

o 

o 

In  C++:  Templates,  in  Java:  Generics.   Der  Begriff  steht  synonym  für  „parametrisierte  Typen“.   Idee:  Es  werden  zusätzliche  Variablen  für  Typen,  sogenannte   Typ-­‐Variablen  eingeführt.     Diese  Typ-­‐Variablen  repräsenSeren  zum  Zeitpunkt  der   ImplemenSerung  unbekannte  Typen.     Erst  bei  der  Verwendung  der  Klassen,  Schninstellen  und   Methoden  werden  diese  Typ-­‐Variablen  durch  konkrete  Typen   ersetzt.     Damit  kann  typsichere  Programmierung  gewährleistet   werden.  

Generics  –  wie  funkSonieren  sie?   14  

Formaler Typparameter

Kein Cast mehr nötig!

Fehlermeldung zur Compilezeit! The method push(String) in the type GenericSimpleStack is not applicable for the arguments (int)

Generics:  Eigenschaoen   15  

o 

Generische  Typen  erlauben  vom  konkreten  Typ  zu  abstrahieren.   ¤ 

¤ 

¤ 

¤ 

¤ 

mit  der  Möglichkeit  zur  Angabe  von  Typparametern  ,  d.h.  Typ  einer   Variable,  eines  Parameters,  eines  Rückgabewertes  etc.  ist  selber  ein   Variable  (type  variable).   Klassen  und  Methoden  haben,  quasi  als  Schablone,  einen  zusätzlichen   Typ-­‐Parameter  (type  parameter),  diese  setzen  dann  die  Typvariablen.   Der  Programmierer  setzt  die  Typ-­‐Parameter  ,  so  wie  er  es  braucht  und   parametriert  damit  die  Klassen  bzw.  Methoden.   Klassen  mit  Typ-­‐Parametern  à  generische  Typen  (generic  types)  bzw.   generische  Klassen  (generic  classes)   Methoden  mit  Typ-­‐Parametern  à  generische  Methoden  (generic   methods)  

  ⇒  ⇒  ⇒ 

Typprüfung  bereits  zur  Compilezeit  à  Typsicherheit.   Verbessert  Lesbarkeit  und  Robustheit  der  Programme.   (Enqernte)  Ähnlichkeiten  zu  Templates  in  C++   15

Generics  DefiniSon   16   ¨  ¨  ¨  ¨ 

DefiniSon  von  Typparametern:  in  spitzen  Klammern  hinter  dem  Klassen-­‐   oder  Interfacenamen.   Typparameter  innerhalb  der  Klasse  bzw.  des  Interfaces  verwendbar  wie   ein  Typ.   Typparameter:  keine  elementaren  Datentypen,    nur    Unterklassen  von   Object  zulässig.   Empfehlung  für  NamenskonvenSon   ¤  ¤ 

Großbuchstabe   E  in  Containerklassen  

Verwendung des Typparameters in Methoden

Formaler Typparameter

Verwendung des Typparameters bei Attributen

Generics  –  Begriffe  und  Beispiele   17  

Name

Beispiel

Generischer Typ (generic type)

List

Formaler Typ-Parameter (formal type parameter)

E

Parametrisierter Typ (parametrized type)

List

Aktueller Typ-Parameter (actual type parameter)

String

Ungebundener Wildcard-Typ (unbounded wildcard type)

List

Raw Type

List

Gebundener Typ-Parameter (bounded type parameter)



Rekursiv gebundener Typ-Parameter (recursive bounded type)



Gebundener Wildcard-Typ (bounded wildcard type)

List  à  bewusstes  „Vergessen“  der  TypinformaSonen  bzw.   zeigen  an,  dass  jede  beliebige  Ausprägung  eines  generischen  Typs  (  =  “alle   Referenztypen“)  möglich  ist.    steht  für  unbekannter  Typ  nicht  für  Objekt  (sonst  gälten  ja  die   Einschränkungen  von  oben).  

o 

Damit  ist  es  möglich  verschiedene  Unterklassen  zusammenzuführen.  

o 

 ist  die  Kurzform  von   bo3 = new Box (); Bei der Erzeugung muss der aktuelle Typparameter angegeben werden, er darf nicht unbekannt bleiben.

Der parametrisierteTyp von bo1 ist Number. Der parametrisierteTyp Typ von bo2 ist unbekannt.

Wildcards:  Beispiel  2   33  

•  Neuer Ansatz mit Generics

„Collection of unknown“

Wildcard

Akzeptiert alle Arten von Collections!

Gebundene  /  Upper  Bound  Wildcards   34  

Auf einem Typ, der mit einem nach oben beschränkten Wildcard parametrisiert ist, dürfen keine Methoden aufgerufen werden, die den Typparameter als Methodenparameter haben. Nur Subtypen von Number sind als unbekannter generischer Typ zulässig! Die Nutzung der Box ist eingeschränkt: setValue() funktioniert nur über die konkrete Box (also bI), aber nicht über die allgemeine Box. Der Zugriff ist unproblematisch. Lösung à später

Gebundene  Wildcards  bei  Parametern   35  

Wildcard für alle Klassen die Unterklasse von Shape sind

Gebundene  /  Lower  Bound  Wildcards   36  

Nur Supertypen von A1 sind als unbekannter generischer Typ zulässig!

Mischen  von  upper  und  lower  bound  Wildcards   37  

Mit der upper bound Wildcard (dem maximalen Typ) funktioniert das Lesen der Daten, aber nicht das Hinzufügen. Lesen von Daten aus generischem Typ è upper bound Wildcards

Nur Supertypen von Number sind als unbekannter generischer Typ zulässig! Mit der lower bound Wildcard (dem minimalen Typ) funktioniert nun das Hinzufügen – aber nicht mehr das Lesen der Daten. Hinzufügen von Objekten zu generischem Typ è lower bound Wildcards

Zusammenfassendes   Beispiel  

38  

Machen wir am Rechner.

Generische  Methoden   39  

Eine  Klasse  kann  ganz  normal  ohne  Generics  deklariert  werden,  aber  mit   Methoden,  die  die  Typen  generisch  vorschreiben.   o  Sowohl  Klassenmethoden  als  auch  Objektmethoden  können  als   generische  Methoden  deklariert  werden,   z.B.    static Stack combine (Stack p).     Angabe von beim Klassennamen entfällt und verschiebt sich auf die Deklaration der Methode.

Rückgabetyp: Objekt der generischen Klasse Stack

Parametertyp: Objekt der generischen Klasse Stack

  o 

o  o 

Im  Gegensatz  zu  Klassen  muss  der  Verwender  den  Typ-­‐Parameter  nicht   explizit  setzen,  der  Compiler  leitet  ihn  aus  den  Typen  des  Aufrufs  ab  (type   inference).   In  seltenen  Fällen  muss  man  den  Typ  für  die  Methode  explizit  angeben.   Interessant  ist  dies  für  USlity-­‐Klassen,  die  nur  staSsche  FunkSonen   anbieten,  aber  selbst  nicht  als  Objekt  vorliegen.  

Generische  Methoden:  Beispiel  1   40  

class MyStack implements Stack

2 Integer Stacks werden zu einem Stack zusammengefasst.

Generische  Methoden:  Beispiel  2   41  

Fehler zur Compilezeit!

Typparameter

Verwendung des Typparameters

Generische  Methoden  mit  gebundenen  Parametern   42  

o 

o  o 

Typ-­‐Parameter  können  -­‐    analog  zu  Wildcards  –  auf   besSmmte  Klassen  beschränkt  werden.    -­‐  schränkt  T  auf  C  und  Subklassen  von  C  ein.    -­‐  schränkt  T  auf  C  und  Superklassen  von  C  ein.  

Generische  Methoden:  Beispiel  3   43  

T muss von Klasse A abgeleitet sein

T muss von den Interfaces I1 und I2 abgeleitet sein

T muss von Klasse A und den Interfaces I1 und I2 abgeleitet sein

Generics  mit  mehreren  Typparametern   44  

Generics  und  Arrays   45  

o 

o  o  o  o 

o 

o 

Generics  und  Arrays  unterscheiden  sich  grundsätzlich  und   harmonieren  im  allgemeinen  schlecht.   Arrays  sind  kovariant  (covariant)   Generics  sind  invariant  (invariant)   Arrays  prüfen  ihren  Typ  zur  Laufzeit  (reified)   Generics  sind  ein  Compilezeitkonstrukt,  prüfen  ihren  Typ   deshalb  zur  Compilezeit  (type  erasure).   Die  Typlöschung  ist  der  Grund  dafür,  das  Arrays  nicht  so   umgesetzt  werden  können,  wie  man  es  sich  naiv  vorstellt.   Es  ist  nicht  möglich  ein  Array  zu  erstellen  aus   ¤  ¤  ¤ 

einem  generischen  Typ  (List[])   einem  parametrierten  Typ  (List[])   einem  Typ-­‐Parameter  (E[])  

Kovarianz,  Kontravarianz,  Invarianz     46  

Vererbung vom Typ des Methodenparameters bzw. Rückgabewerts

Typhierarchie des Methodenparameters ist entgegen der Vererbungshierarchie von ClassA und ClassB

Typhierarchie des Rückgabewertes der Methode ist mit der Vererbungshierarchie von ClassA und ClassB

Typhierachie des Methodenparameters bleibt unverändert

Quelle: Wikipedia

RunSme-­‐Klassen   47  

o 

Was  gibt  das  folgende  Programm  aus?  

Gibt „true“ aus, weil alle Instanzen einer generischen Klasse dieselbe Runtime-Klasse haben

Anwendungsbeispiel:  Queue   48  

Anwendungsbeispiel:  List   49  

Anwendungsbeispiel:  Node   50  

Einsatz  von  Generics   51  

o 

Allgemein   ¤  ¤ 

o 

o  o 

Generics  sind  eine  Form  von  Polymorphie.   Diese  ist  immer  dann  sinnvoll,  wenn  der  Code  wiederverwendbar  sein   soll.  

Generics  kontra  Polymorphie  durch  Subtyping:   ¤ 

Generics  für  die  Typsicherheit.  

¤ 

Vorteil  gegenüber  Casts  durch  frühere  Fehlererkennung.  

Der  Entwickler  wird  nicht  gezwungen  Generics  zu  verwenden.   Eine  unchecked  Warnung  weist  darauf  hin,  dass  die   Typsicherheit  nicht  gewährleistet  ist.  

Zusammenfassung   52  

o 

Generics  erlauben  typsicher  zu  programmieren   ¤ 

¤ 

Typprüfungen  erfolgen  bereits  zur  Compilezeit  nicht  erst  zur  Laufzeit.   D.h.  Fehler  treten  an  den  Stellen  auf,  wo  sie  verursacht  werden.   Generics  helfen  dabei  Programme  robuster  und  weniger  fehleranfällig   zu  machen.   n  n 

Das  Wegfallen  von  Casts  macht  den  Code  übersichtlicher.   Bedingungen  lassen  sich  besser  und  einfacher  ausdrücken.  

o 

Generische  Klassen  können  leicht  wiederverwendet  werden.  

o 

In  Bezug  auf  Arrays  ist  das  Konzept  noch  nicht  ausgereio.  

Generics  –  Erweiterungen  in  Java  7   53  

Mit  Java  7  ist  die  Typ-­‐Inferenz  für  Generics  deutlich  verbessert   worden:   o  In  den  meisten  SituaSonen  muss  man  den  Typ-­‐Parameter  nur     noch  bei  der  DeklaraSon  setzen.   o  Bei  der  Objekterzeugung  kann  die  Angabe  des  Typ-­‐ Parameters  durch  den  diamond    ersetzt  werden.     Beispiele:   List list = new ArrayList();! Map map = new HashMap();! Set set = new HashSet();!

Weitere  Infos  zu  Generics   54  

o  o 

hnp://java.sun.com/j2se/1.5/pdf/generics-­‐tutorial.pdf   hnp://angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.pdf  

Suggest Documents