Objektorientierte Programmierung

Slides:



Advertisements
Ähnliche Präsentationen
M a r c – o l i v e r p a h l Informatik I – Kapitel 7 Klassen und höhere Datentypen Zusammenfassung des Kapitel 7 Küchlin, Weber, Einführung in die Informatik,
Advertisements

der Universität Oldenburg
der Universität Oldenburg
Objektorientierte Programmierung
der Universität Oldenburg
der Universität Oldenburg
Imperative Programmierung
der Universität Oldenburg
der Universität Oldenburg
Einführung in die Informatik: Programmierung und Software-Entwicklung
Anwendungen des OODM auf die ADB / NDB
PKJ 2005/1 Stefan Dissmann Vorwoche - Klasse public class Studierende { private String name, vorname, studiengang; private int matNr, semester; private.
Zusammenfassung des Kapitels 8
der Universität Oldenburg
der Universität Oldenburg
Imperative Programmierung -Entwicklungswerkzeuge
Objektorientierte Programmierung
Objektorientierte Programmierung Definition von Klassen
Programmierkurs Java WS 98/99 Vorlesung 15 Dietrich Boles 17/02/99Seite 1 Programmierkurs Java Vorlesung im WS 1998/1999 am FB Informatik der Universität.
der Universität Oldenburg
Prof. Dr.-Ing. habil. B. Steinbach - Informatik / Softwaretechnologie und Programmierungstechnik - Institut für Informatik F Verteilte Software - Java.
Verteilte Software - Java - Prozedurale Programmierung 1
Java: Objektorientierte Programmierung
Java: Dynamische Datentypen
Java: Grundlagen der Objektorientierung
Konstruktoren.
FOR Anweisung. Aufgabe : Ausgabe aller ganzen Zahlen von 0 bis 100 auf dem Bildschirm.
M a r c – o l i v e r p a h l Die ObjektOrientierte Mühle Das Beispiel soll noch einmal das Konzept der Objektorientiertheit erläutern. Dabei werden außerdem.
Praktikum Entwicklung und Einsatz von Geosoftware I - Sitzung 6 Model-View-Controler als Grundlage für Nutzerschnittstellen Sommersemester 2003 Lars Bernard.
Dynamische Webseiten Java servlets.
Imperative Programmierung Funktionen und Parameter
Objektorientierte Programmierung JDK-Klassenbibliothek
Programmieren mit JAVA
Programmieren mit JAVA
Vererbung Spezialisierung von Klassen in JAVA möglich durch
PRJ 2007/1 Stefan Dissmann Motivation Problem: gleiche Datenstrukturen werden für verschiedene Objekte gebraucht: z.B. Listen von Studierenden, Kunden,
PKJ 2005/1 Stefan Dissmann Ausblick Es fehlen noch: Möglichkeiten zum Strukturieren größerer Programme Umgang mit variabler Zahl von Elementen Umgang mit.
PKJ 2005/1 Stefan Dissmann Rückblick auf 2005 Was zuletzt in 2005 vorgestellt wurde: Klassen mit Attributen, Methoden und Konstruktoren Referenzen auf.
PKJ 2005/1 Stefan Dissmann Zusammenfassung Bisher im Kurs erarbeitete Konzepte(1): Umgang mit einfachen Datentypen Umgang mit Feldern Umgang mit Referenzen.
PKJ 2005/1 Stefan Dissmann Zusammenfassung der Vorwoche Variable stehen für (einen) Wert, der sich im Programmablauf ändern kann. Variablen besitzen einen.
Zusammenfassung Vorwoche
PKJ 2005/1 Stefan Dissmann Klassenhierarchie Person Kunde Goldkunde Lieferant Object.
PKJ 2005/1 Stefan Dissmann Zusammenfassung Vorwoche Methoden sind mit einem Namen versehene Programmabschnitte besitzen Rückgabetyp, Namen, Parameterliste.
Programmiermethodik SS2010 © 2010 Albert Zündorf, University of Kassel 1 Gesamtvorgehen 1. Textuelle Szenarios 2. Objektdiagramme 3. Klassendiagramm 4.
Proxy Pattern Vorlesung Design Patterns Sieglinde Heinrich
DVG Klassen und Objekte
05 - Reflection Das Reflection API Reflection2 Ziel Es kommt vor, dass eine Methode ein Objekt als Parameter übergeben bekommt, ohne dass bekannt.
Java in 9 Folien Besser: Online-Buch Go to Java 2.
Einführung in die Programmierung Datensammlung
Informatikunterricht mit Java
Seite 1 Interface - Konzept Ein Interface führt einen neuen Datentyp ein: interface Frau {... } Das Interface enthält Deklarationen ( keine Definitionen.
Sommersemester 2004 Jan Drewnak Entwicklung und Einsatz von Geosoftware I Praktikum Sitzung 6 Sitzung 6: Model-View-Controller als Grundlage.
PRJ 2007/1 Stefan Dissmann Verkettete datenstruktur: Liste Problem: Liste, die eine beliebige Zahl von Elementen verwaltet Operationen: Erzeugen, Anfügen,
OO implementieren Teil IV Objekte erzeugen. © René ProbstModul 226IV - 2 Von der Klasse zum Objekt Plan Bau Objekt Klasse Instanzierung Objekt Das Objekt.
Javakurs FSS 2012 Lehrstuhl Stuckenschmidt
Javakurs FSS 2012 Lehrstuhl Stuckenschmidt
Parallel Programming Thread Synchronization. Heute 1. Lösung zu Assignment 2 2. Erstellen und Starten von Threads in Java 3. Das synchronized Schlüsselwort.
Equals, Hashcode und CompareTo Micha Kessler
CuP - Java Neunte Vorlesung Entspricht Kapitel 4.2 und 5 des Skriptums
CuP - Java Vierte Vorlesung Entspricht ungefähr Kapitel 2.1 des Skriptums Montag, 14. Oktober 2002.
CuP - Java Zwölfte Vorlesung Klassen – Komposition und Vererbung Freitag, 15. November 2002.
Learning By Doing Ereignissteuerung (Events) prozedural ereignisgesteuert Unterprogrammaufruf an fest codierter Stelle Wann immer der Event auftritt, führe.
Learning By Doing Konstruktoren Gleicher Name wie die Klasse Zur Initialisierung des Objekts, insbesondere mit Parametern Wir immer bei der Objekterzeugung.
Java Thread Scheduling Jin Zhou Proseminar Java Thread Scheduling November 2000.
Programmiervorkurs WS 2014/15 Methoden
Java-Kurs - 8. Übung Besprechung der Hausaufgabe.
3. Beschreibung von Abläufen durch Algorithmen 3.4 Zufall
Java-Kurs - 3. Übung Hausaufgabe Arrays For-Schleifen.
Programmierkurs JavaUE 4 Anweisungen und ProgrammeDietrich BolesSeite 1 Programmierkurs Java Dr. Dietrich Boles Teil Imperative Programmierung Unterrichtseinheit.
Vererbung in Java. public abstract class Form { protected int breite; protected int hoehe; protected String farbe; /** * Erzeuge eine Form der Breite.
 Präsentation transkript:

Objektorientierte Programmierung Programmierkurs Java Teil Objektorientierte Programmierung Unterrichtseinheit 38 Generics Dr. Dietrich Boles

Gliederung Generics Typ-Parameter mit Einschränkungen Motivation Generische Klassen Klassendefinition Objekte / Objektvariablen Übersetzung Typ-Kompatibilität Generische JDK-Klassen Iterator Vector Beispiel Typ-Parameter mit Einschränkungen Vererbung Interfaces Arrays Wildcards new static Generische Methoden Motivation Beispiele Zusammenfassung

Motivation / Problem Simulation eines Getränkehandels Quelle: J. Nowak. Fortgeschrittene Programmierung mit Java 5,dpunkt. Gegeben: vielerlei Getränke Gewünscht: typisierte Flaschen, die nur mit Bier, Rotwein oder Weißwein gefüllt werden können Drink Beer Wine WhiteWine RedWine

Motivation / Ausgangslage abstract class Drink { } class Beer extends Drink { private String brewery; public Beer(String brewery) { this.brewery = brewery; } public String getBrewery() { return this.brewery; } public String toString() { return this.getClass().getName() + "[" + this.brewery + "]“; } } abstract class Wine extends Drink { private String region; public Wine(String region) { this. region = region; } public String getRegion() { return this.region; } public String toString() { return this.getClass().getName() + "[" + this.region + "]"; } class WhiteWine extends Wine { public WhiteWine(String region) { super(region); } class RedWine extends Wine { public RedWine(String region) { super(region); }

Motivation / erste Lösung class Bottle { private Drink content; public boolean isEmpty() { return this.content == null; } public void fill(Drink content) { this.content = content; public Drink empty() { Drink content = this.content; this.content = null; return content; ... Bottle beerBottle = new Bottle(); beerBottle.fill(new WhiteWine("Burgunder")); Beer beer = (Beer)beerBottle.empty(); // ClassCastException! Lösung: polymorphe Klasse Probleme: - keine korrekte Lösung - Typ-Unsicherheit

Motivation / zweite Lösung abstract class DrinkBottle {} class BeerBottle extends DrinkBottle { private Beer cont; public void fill(Beer content) { this.cont = content; } public Beer empty() { Beer c=this.cont; this.cont=null; return c; } } abstract class WineBottle extends DrinkBottle {} class WhiteWineBottle extends WineBottle { private WhiteWine cont; public void fill(WhiteWine content) { this.cont = content; } public WhiteWine empty() { WhiteWine c=this.cont; this.cont=null; return c; } class RedWineBottle extends WineBottle { private RedWine cont; public void fill(RedWine content) { this.cont = content; } public RedWine empty() { RedWine c = this.cont; this.cont = null; return c; } Lösung: Getränk-spezifische Flaschen Problem: Keine Vererbung, keine wirkliche Polymorphie!

Motivation / dritte Lösung (1) class Bottle<T> { private T content; public boolean isEmpty() { return this.content == null; } public void fill (T content) { this.content = content; } public T empty() { T content = this.content; this.content = null; return content; } Lösung: - Generische (parametrisierte) Klasse - T ist formaler Typ-Parameter (Typ-Variable) der Klasse Bottle

Motivation / dritte Lösung (2) Bottle<Beer> beerBottle = new Bottle<Beer>(); Bottle<WhiteWine> whiteWineBottle = new Bottle<WhiteWine>(); beerBottle.fill(new Beer("Veltins")); beerBottle.fill(new WhiteWine("Burgunder")); // Fehlermeldung durch Compiler! whiteWineBottle.fill(new WhiteWine("Burgunder")); Beer beer = beerBottle.empty (); System.out.println (beer); WhiteWine whiteWine = whiteWineBottle.empty (); System.out.println (whiteWine); Aktueller Typ-Parameter (Klasse)

Generische Klassen / Klassendefinition class C<T> { ... } class D<T> extends T { } class E<T> { T obj; } interface I<T1, T2> { public void setze(T1 obj1, T2 obj2); } class F<T4, T5, T6> implements I<T4, T6> { public T5 liefere() { ...} public void setze(T4 obj1, T6 obj2) { ... } T kann im weiteren Klassenkopf und im Klassenrumpf (fast) überall da verwendet werden, wo Klassennamen stehen können

Generische Klassen / Objekte und Objektvariablen class C<T> { public T f(T t) {...} } class A { } class B { } C<A> obj = new C<A>(); C<B> obj2 = new C<B>(); A a = obj.f(new A()); B b = obj2.f(new B()); A a2 = obj.f(new B()); // Fehlermeldung durch Compiler Formaler Typ-Parameter Parametrisierte Klasse / Typ Aktueller Typ-Parameter (Klasse, kein Standarddatentyp)

Generische Klassen / Übersetzung class C<T> { T t; T f(T t) { T t1 = t; this.t = t1; String str = t.toString(); return this.t; } class C { Object t; Object f(Object t) { Object t1 = t; this.t = t1; Compiler Raw-Type Daher erlaubt: C obj = new C(); + Meta-Informationen!

Generische Klassen / Typ-Kompatibilität class C<T> { ... } class A { } class B { } class D extends A { } C<B>  C<A> // C<A> obj = new C<B>(); Fehler C<D>  C<A> // C<A> obj = new C<D>(); Fehler C<A>  C<Object> // C<Object> = new C<A>(); Fehler C<A>  Object // Object obj = new C<A>(); ok

Generische JDK-Klassen / java.util.Iterator public interface Iterator<T> { public boolean hasNext(); public T next(); } public interface Iterable<T> { // in java.lang public java.util.Iterator<T> iterator();

Generische JDK-Klassen / java.util.Vector public class Vector<T> extends java.util.AbstractList<T> implements Iterable<T>, ... { public Vector(); public Vector(int initCapacity); public boolean add(T obj); public boolean contains(Object obj); public T elementAt(int index); public T get(int index); public void insertElementAt(T o,int i); public boolean remove(Object obj); public int size(); public java.util.Iterator<T> iterator(); ... }

Generische JDK-Klassen / Beispiel import java.util.Vector; import java.util.Iterator; public class IteratorBspMitCast { public static void main(String[] args) { Vector speicher = new Vector(); speicher.add(4711); speicher.add(46); speicher.add(33); int summe = 0; Iterator iter = speicher.iterator(); while (iter.hasNext()) { summe += (Integer)iter.next(); } System.out.println(summe); Raw-Type Cast notwendig! Compiler-Warnung: ... uses unsafe operations

Generische JDK-Klassen / Beispiel import java.util.Vector; import java.util.Iterator; public class IteratorBsp { public static void main(String[] args) { Vector<Integer> speicher = new Vector<Integer>(); speicher.add(4711); speicher.add(46); speicher.add(33); int summe = 0; Iterator<Integer> iter = speicher.iterator(); while (iter.hasNext()) { summe += iter.next(); } System.out.println(summe); Kein Cast notwendig!

Generische JDK-Klassen / Beispiel import java.util.Vector; public class IteratorBspFor { public static void main(String[] args) { Vector<Integer> speicher = new Vector<Integer>(); speicher.add(4711); speicher.add(46); speicher.add(33); int summe = 0; for (Integer i : speicher) { summe += i; } System.out.println(summe); neue for-Schleife

Typ-Parameter mit Einschränkungen Motivationsproblem: Bottle<Object> ist keine Getränkeflasche! Lösung: Einschränkung des Typ-Parameters class Bottle<T extends Drink> { /* wie auf Folie 7 */ } class Petrol { } class Stout extends Beer { ... } Bottle<Drink> drinkBottle = new Bottle<Drink>(); Bottle<Beer> beerBottle = new Bottle<Beer>(); Bottle<Object> objectBottle = new Bottle<Object>(); // Fehlermeldung durch Compiler Bottle<Petrol> petrolBottle = new Bottle<Petrol>(); Bottle<Stout> stoutBottle = new Bottle<Stout>();

Typ-Parameter mit Einschränkungen / Übersetzung class A { public void doIt() {...} } class C<T extends A> { T t; T f(T t) { T t1 = t; this.t = t1; this.t.doIt(); return this.t; class C { A t; A f(A t) { A t1 = t; this.t = t1; this.t.doIt(); return this.t; } Compiler

Vererbung class A { } class B<T extends A> { public void f(T t) { ... } } class C<T> extends A { } class D<T extends A> extends B<T> { } class E extends B<A> { public void f(A obj) { ... } // Überschreiben public void f(Object obj) { ... } // Überladen

Interfaces class A { } class B { } interface I<T1 extends A, T2 extends B> { public void f1(T1 t); public void f2(T2 t); } class C implements I<A, B> { public void f1(A t) { ... } public void f2(B t) { ... } class D implements I<A, A>, I<B, B> { ... } // Fehler: dasselbe Interface nicht zweimal implementieren

Arrays mit parametrisierten Klassen (1) Motivationsproblem: Klasse für Getränke-spezifische Getränkekästen Problem: Arrays mit parametrisierten Klassen sind nicht erlaubt Lösung: class BottleBox<T extends Drink> { private Object[] bottles; private int count = 0; public BottleBox(int number) { // this.bottles = new T[number]; nicht erlaubt this.bottles = new Object[number]; } public void add(Bottle<T> bottle) { this.bottles[this.count] = bottle; this.count++; public Bottle<T> getBottle(int index) { return (Bottle<T>)this.bottles[index]; Internes sicheres (!) Cast

Arrays mit parametrisierten Klassen (2) BottleBox<Beer> beerBottleBox = new BottleBox<Beer>(6); // Bierkasten füllen for (int i = 0; i < 6; i++) { Bottle<Beer> beerBottle = new Bottle<Beer>(); beerBottle.fill(new Beer("Jever")); beerBottleBox.add(beerBottle); } Bottle<RedWine> wineBottle = new Bottle<RedWine>(); beerBottleBox.add(wineBottle); // Fehlermeldung ... // Bierkasten leeren Bottle<Beer> beerBottle = beerBottleBox.getBottle(i); Beer beer = beerBottle.empty (); System.out.println(beer);

Wildcards (1) Motivationsproblem: Klasse für Getränkekästen mit beliebigen Flaschen Lösung: „Wildcards“ class BottleBox { private Object[] bottles; private int count = 0; public BottleBox(int number) { this.bottles = new Object[number]; } public void add(Bottle<? extends Drink> bottle) { this.bottles[this.count] = bottle; this.count++; public Bottle<? extends Drink> getBottle(int index) { return (Bottle<? extends Drink>)this.bottles[index];

Wildcards (2) BottleBox box = new BottleBox(6); // Füllen Bottle<Beer> beerBottle = new Bottle<Beer>(); beerBottle.fill(new Beer("Veltins")); box.add (beerBottle); Bottle<WhiteWine> whiteWineBottle = new Bottle<WhiteWine>(); whiteWineBottle.fill (new WhiteWine("Burgunder")); box.add (whiteWineBottle); // Leeren for (int i = 0; i < 6; i++) { Bottle<? extends Drink> bottle = box.getBottle (i); Drink drink = bottle.empty (); System.out.println(drink); }

Wildcards (3) class A { } class B { } class C<T> { } C<A> ca = new C<A>(); // ok C<Object> cobj = new C<A>(); // Fehler C obj = new C<A>(); // ok, aber möglichst vermeiden C<?> c1 = new C<A>(); // ok C<?> c2 = new C<B>(); // ok ? steht für irgendeinen Typ

Wildcards (4) Semantische Ungereimtheit Motivationsproblem: Klasse für Getränke-spezifische Getränkekästen Problem der Lösung auf Folie 22: BottleBox<Beer> Lösung: class BottleBox<T extends Bottle<? extends Drink>> { private Object[] bottles; private int count = 0; public BottleBox(int number) { this.bottles = new Object[number]; } public void add(T bottle) { this.bottles[this.count] = bottle; this.count++; public T getBottle(int index) { return (T)this.bottles[index]; Semantische Ungereimtheit

Wildcards (5) BottleBox<Bottle<Beer>> beerBottleBox = new BottleBox<Bottle<Beer>>(6); // Bierkasten füllen for (int i = 0; i < 6; i++) { Bottle<Beer> beerBottle = new Bottle<Beer>(); beerBottle.fill(new Beer("Jever")); beerBottleBox.add(beerBottle); } ... // Bierkasten leeren Bottle<Beer> beerBottle = beerBottleBox.getBottle(i); Beer beer = beerBottle.empty (); System.out.println(beer);

new class A { } class C<T> { T t = new T(); // Fehlermeldung; Grund: Übersetzung // von T nach Object }

static Grund: Der Compiler generiert nur eine (!) Klasse. class A { } Class B { } class C<T> { static T t; // Fehlermeldung static C<T> c; // Fehlermeldung } C<A> ca = new C<A>(); C<B> cb = new C<B>(); Grund: Der Compiler generiert nur eine (!) Klasse. Beide Objekte würden sich die statischen Attribute teilen.

Generische Methoden / Motivation (1) Motivationsproblem: Umfüllen von Flaschen Mögliche Lösung: class BottleTransfuser<T extends Drink> { void transfuse(Bottle<T> fromBottle, Bottle<T> toBottle) { T drink = fromBottle.empty(); toBottle.fill(drink); } BottleTransfuser<Beer> beerTransfuser = new BottleTransfuser<Beer>(); ... Problem: beerTransfuser kann nur Bierflaschen umfüllen!

Generische Methoden / Motivation (2) allgemeiner Lösung: Generische Methoden class BottleTransfuser { <T extends Drink> void transfuse (Bottle<T> fromBottle, Bottle<T> toBottle) { T drink = fromBottle.empty(); toBottle.fill(drink); } BottleTransfuser transfuser = new BottleTransfuser (); Bottle<Beer> b1 = new Bottle<Beer>(); b1.fill(new Beer("Jever")); Bottle<Beer> b2 = new Bottle<Beer>(); transfuser.transfuse(b1, b2); Bottle<WhiteWine> b3 = new Bottle<WhiteWine>(); b3.fill(new WhiteWine("Burgunder")); Bottle<WhiteWine> b4 = new Bottle<WhiteWine>(); transfuser.transfuse(b3, b4); transfuser.transfuse(b1, b4); // Fehlermeldung

Generische Methoden / Beispiele (1) class A { public void f() {} } class B extends A { } class C { public <T> void f1(T t) { String str = t.toString(); } public static <T extends A> void f2(T t) { t.f(); C obj = new C(); C.f2(new A()); obj.f1("Hallo"); C.f2(new B()); obj.f1(4711); C.f2("Hallo"); // Fehlermeldung

Generische Methoden / Beispiele (2) class C { public static <T> void f3(T t1, T t2) { } public static <T> T f4(T t1, T t2) { return Math.random() < 0.5 ? t1 : t2; } C.f3(11, "Hallo"); // Supertyp Object C.f3("Hallo", 11); // Supertyp Object String s2 = C.f4("Hallo", "World"); // Supertyp String String s1 = C.f4(11, "Hallo"); // Fehlermeldung Comparable c1 = C.f4(11, "World"); // Supertyp Comparable Die "T" müssen einen gemeinsamen Supertyp haben

Zusammenfassung Generics: Parametrisierte Klassen Sinn und Zweck: Semantische Korrektheit Vermeidung von Type-Casts Vermeidung von ClassCast-Exceptions