Praktische Softwaretechnologie Vorlesung 3 Martin Giese Johann Radon Institute for Computational and Applied Mathematics Österr. Akademie der Wissenschaften Linz PSWT 2006 – 24. Oktober 2006 – p.1/26 Klassendefinition class Point { // Felder ... // Methoden ... } PSWT 2006 – 24. Oktober 2006 – p.2/26 Klassendefinition public abstract class Point extends SuperClass { // Felder ... // Methoden ... } PSWT 2006 – 24. Oktober 2006 – p.2/26 Klassendefinition class Point { /** The x-coordinate */ double x; /** The y-coordinate */ double y; // Methoden ... } PSWT 2006 – 24. Oktober 2006 – p.2/26 Klassendefinition class Point { /** The x-coordinate */ public double x; /** The y-coordinate */ public double y; // Methoden ... } PSWT 2006 – 24. Oktober 2006 – p.2/26 Klassendefinition class Point { /** The x-coordinate */ private double x; /** The y-coordinate */ private double y; // Methoden ... } PSWT 2006 – 24. Oktober 2006 – p.2/26 Klassendefinition class Point { /** The x-coordinate */ private double x; /** The y-coordinate */ private double y; /** Return the point’s x-coordinate */ public double getX() { return x; } } PSWT 2006 – 24. Oktober 2006 – p.2/26 Klassendefinition class Point { /** The x-coordinate */ private double x; /** The y-coordinate */ private double y; /** Return the point’s x-coordinate */ public double getX() { return x; } /** Set the point’s x-coordinate */ public void setX(double newX) { x = newX; } } PSWT 2006 – 24. Oktober 2006 – p.2/26 Klassendefinition class Point { /** The x-coordinate */ private double x; /** The y-coordinate */ private double y; /** Test whether other point is equal to this */ public boolean eqPoint(Point other) { return (x == other.x) && (y == other.y); } } PSWT 2006 – 24. Oktober 2006 – p.2/26 Klassendefinition class Point { /** The x-coordinate */ private double x; /** The y-coordinate */ private double y; /** Test whether other point is equal to this */ public boolean eqPoint(Point other) { return (this.x == other.x) && (this.y == other.y); } } PSWT 2006 – 24. Oktober 2006 – p.2/26 Klassendefinition class Point { /** The x-coordinate */ private double x; /** The y-coordinate */ private double y; /** Test whether other point is equal to this */ public boolean eqPoint(Point other) { return (getX() == other.getX()) && (getY() == other.getY()); } } PSWT 2006 – 24. Oktober 2006 – p.2/26 Klassendefinition class Point { /** The x-coordinate */ private double x; /** The y-coordinate */ private double y; /** Test whether other point is equal to this */ public boolean eqPoint(Point other) { return (this.getX() == other.getX()) && (this.getY() == other.getY()); } } PSWT 2006 – 24. Oktober 2006 – p.2/26 Klassendefinition class Point { /** The x-coordinate */ private double x; /** The y-coordinate */ private double y; /** return a String representation of this point */ public String toString() { return "(" + x + "," + y + ")"; } } PSWT 2006 – 24. Oktober 2006 – p.2/26 Klassendefinition class Point { /** The x-coordinate */ private double x; /** The y-coordinate */ private double y; /** return a String representation of this point */ public String toString() { return "(" + x + "," + y + ")"; } } ... Point p = ... String s = "The point " + p; System.out.println(p); ... PSWT 2006 – 24. Oktober 2006 – p.2/26 Klassendefinition class Point { /** The x-coordinate */ private double x; /** The y-coordinate */ private double y; /** Construct a new point with given coordinates */ public Point(double x, double y) { this.x = x; this.y = y; } } PSWT 2006 – 24. Oktober 2006 – p.2/26 Klassendefinition class Point { /** The x-coordinate */ private double x; /** The y-coordinate */ private double y; /** Construct a new point with given coordinates */ public Point(double x, double y) { this.x = x; this.y = y; } } ... Point p = new Point(10.0, 20.0); ... PSWT 2006 – 24. Oktober 2006 – p.2/26 Klassendefinition class Point { /** The x-coordinate */ private double x; /** The y-coordinate */ private double y; /** Construct a new point located at the origin */ public Point() { this(0.0, 0.0); } } ... Point p = new Point(); ... PSWT 2006 – 24. Oktober 2006 – p.2/26 Benutzung class UsePoint { public static void comparePoints(Point p1, Point p2) { System.out.print("Points " + p1 + " and " + p2 + " are "); if (p1.eqPoint(p2)) { System.out.println("equal."); } else { System.out.println("unequal."); } } public static void main(String[] args) { Point p1 = new Point(); Point p2 = new Point(1.0,2.0); comparePoints(p1,p2); p1.setX(1.0); p1.setY(2.0); comparePoints(p1,p2); } } PSWT 2006 – 24. Oktober 2006 – p.3/26 Unterklassen class WeightedPoint extends Point { private double weight; } PSWT 2006 – 24. Oktober 2006 – p.4/26 Unterklassen class WeightedPoint extends Point { private double weight; public WeightedPoint(double x, double y, double w) { super(x,y); weight = w; } } PSWT 2006 – 24. Oktober 2006 – p.4/26 Unterklassen class WeightedPoint extends Point { private double weight; public WeightedPoint(double x, double y, double w) { super(x,y); weight = w; } public WeightedPoint(double x, double y) { this(x, y, 1.0); } } PSWT 2006 – 24. Oktober 2006 – p.4/26 Unterklassen class WeightedPoint extends Point { private double weight; public WeightedPoint(double x, double y, double w) { super(x,y); weight = w; } public WeightedPoint(double x, double y) { this(x, y, 1.0); } public WeightedPoint() { weight = 1.0; } } PSWT 2006 – 24. Oktober 2006 – p.4/26 Unterklassen class WeightedPoint extends Point { private double weight; public double getWeight() { return weight; } public void setWeight(double weight) { this.weight = weight; } } PSWT 2006 – 24. Oktober 2006 – p.4/26 Unterklassen class WeightedPoint extends Point { private double weight; public boolean eqWeightedPoint(WeightedPoint other) { return eqPoint(other) && (this.weight == other.weight); } } PSWT 2006 – 24. Oktober 2006 – p.4/26 Unterklassen class WeightedPoint extends Point { private double weight; public boolean eqWeightedPoint(WeightedPoint other) { return eqPoint(other) && (this.weight == other.weight); } public String toString() { return super.toString() + "*" + weight; } } ➠ ”Überschreiben“ (overloading) der Methode toString() PSWT 2006 – 24. Oktober 2006 – p.4/26 Statischer und Dynamischer Typ • statischer Typ von Ausdrücken: wird vom Compiler ermittelt und überprüft • dynamischer Typ von Objekten/Referenzen: ergibt sich zur Laufzeit Ausdruck hat statischen Typ wird ausgewertet zu Objektreferenz hat dynamischen Typ A ist Untertyp von B PSWT 2006 – 24. Oktober 2006 – p.5/26 Implementierung Methodentabelle fuer Point p1: getX x=1.0 setX y=2.0 ... getX() aus Point setX(double) aus Point toString andere Methoden aus Point Methodentabelle fuer WeightedPoint wp1: toString() aus Point getX x=1.0 setX y=2.0 ... w=1.0 toString() aus WeightedPoint toString setWeight(double) aus WeightedPoint setWeight PSWT 2006 – 24. Oktober 2006 – p.6/26 Implementierung 2 Zugriff auf Felder: Java: p1.x = 1; C: p1[1] = 1; Aufruf von Methoden: Java: p1.toString(); C: p1[0][6](p1); Java: wp1.setWeight(2.0); C: wp1[0][7](wp1,2.0); Java: super.toString(); C: ??? PSWT 2006 – 24. Oktober 2006 – p.7/26 Überladen von Methoden (overloading) Überschreiben (overriding): • Methode einer Unterklasse überschreibt eine Methode einer Oberklasse. • Tatsächliche Implementierung wird zur Laufzeit bestimmt. . . • . . . abhängig vom dynamischen Typ des Empfängers. Überladen (overloading): • Mehrere Methoden (vielleicht einer Klasse) haben gleichen Namen • Welche gemeint ist wird vom Compiler bestimmt. . . • . . . abhängig vom statischen Typ der Argumente. PSWT 2006 – 24. Oktober 2006 – p.8/26 Überladen von Methoden 2 Beispiel: public class PrintStream { ... println(boolean b) {...} println(char c) {...} println(int i) {...} ... println(Object o) {...} ... } PSWT 2006 – 24. Oktober 2006 – p.9/26 Überladen von Methoden 2 Beispiel: public class PrintStream { ... println(boolean b) {...} println(char c) {...} println(int i) {...} ... println(Object o) {...} ... } public class GermanPrintStream extends PrintStream { println(boolean b) {...} } PSWT 2006 – 24. Oktober 2006 – p.9/26 Statische Felder Felder mit Kennzeichnung static von allen Objekten einer Klasse geteilt. class A { public static int x; } Zugriff: A a = ...; a.x = a.x + 1; oder (besser) A.x = A.x + 1; PSWT 2006 – 24. Oktober 2006 – p.10/26 Statische Methoden Methoden mit Kennzeichnung static • können nur auf statische Felder zugreifen • können ohne Objekt der Klasse aufgerufen werden • können this nicht verwenden class A { public static void initClass(); } Zugriff: A a = ...; a.initClass(); A.initClass(); // besser! PSWT 2006 – 24. Oktober 2006 – p.11/26 Packages Jede Java Klasse ist Teil einer „Package“. Datei HelloWorld.java im aktuellen Verzeichnis: class HelloWorld { ... } „default package“ Benutzung: new HelloWorld(...) PSWT 2006 – 24. Oktober 2006 – p.12/26 Packages Jede Java Klasse ist Teil einer „Package“. Datei PrintStream.java im Verzeichnis java\io: package java.io; class PrintStream { ... } package java.io Benutzung: new java.io.PrintStream(...) PSWT 2006 – 24. Oktober 2006 – p.12/26 Packages 2 Verwendung von kurzem PrintStream statt java.io.PrintStream möglich: • in anderen Klassen der java.io Package. • Nach Import import java.io.PrintStream; am Anfang der Klasse, zwischen „package“ und „class“ • Nach Import import java.io.*; • Import für java.lang package automatisch. PSWT 2006 – 24. Oktober 2006 – p.13/26 Package Namen Merke: Hierarchie (java.io ⊆ java) hat keine Bedeutung Namen üblicherweise nach Internet domains, z.B.: Bundesministerium für Finanzen: http://www.bmf.gv.at/ Package Namen: at.gv.bmf.... Aber: Standard libraries java.lang, java.io, java.util, . . . Standarderweiterungen: javax.print, javax.crypto, . . . PSWT 2006 – 24. Oktober 2006 – p.14/26 Sichtbarkeiten Für Felder und Methoden: 4 unterschiedliche Sichtbarkeiten: modifier sichtbar... private nur in der selben Klasse (default) in allen Klassen der selben Package protected in der selben Package und in Unterklassen public von jeder Klasse aus Klassen nur public oder default Tatsächliche Regeln etwas komplizierter, bei Bedarf nachlesen. PSWT 2006 – 24. Oktober 2006 – p.15/26 Richtlinien für Sichtbarkeiten • Package: überschaubare Einheit von zusammenspielenden Klassen. • Felder so gut wie immer private • Klassen public wenn sie Teil des Leistungsangebots der Package sind. • Methoden public wenn sie Teil der dokumentierten öffentlichen Schnittstelle der Klasse sind. • Methoden private wenn sie „Implementierungsdetail“ sind. • Methoden package-private für das Zusammenspiel von teilweise package-private Klassen. • protected nur bei Klassen die zum Vererben entworfen sind. PSWT 2006 – 24. Oktober 2006 – p.16/26 Aufgabe 5 Vertiefen und Ergänzen des Stoffs durch Lesen im Java Tutorial: http://java.sun.com/docs/books/tutorial/java/index.html • Classes and Objects • Insbesondere den Teil über „Nested Classes“ • „enum types“ kommen noch in der Vorlesung • „annotations“ vorerst unwichtig PSWT 2006 – 24. Oktober 2006 – p.17/26 Aufgabe 6 Betrachte das Programm aus den Klassen OverA, OverB, OverTest. Welche der Methoden aus OverA, OverB sind überladen, und welche werden von welchen überschrieben? Lasse das Hauptprogramm in OverTest laufen. Erkläre detailliert die Ausgabe! PSWT 2006 – 24. Oktober 2006 – p.18/26 Aufgabe 7 Programmiere eine Klasse Stack mit: • public Stack(int n) erzeugt einen neuen Stack mit Platz für n Objekte. • public void push(String s) legt s oben auf den Stack. • public String pop() entfernt das oberste Element vom Stack und gibt es zurück • public boolean isEmpty() antwortet ob der Stack leer ist. • public String toString() gibt alle Elemente des Stacks in einem String aus. PSWT 2006 – 24. Oktober 2006 – p.19/26 Aufgabe 7 (forts.) Schreibe ein Hauptprogramm in einer anderen Klasse, das • Zwei Stacks erzeugt • Einige Strings in den ersten Stack schiebt • Den Stack als Text ausgibt. • In einer Schleife alle Elemente vom ersten Stack „popt“ und auf den zweiten „pusht“ • Den zweiten Stack ausgibt. PSWT 2006 – 24. Oktober 2006 – p.20/26 Aufgabe 7 (forts.) Schreibe nun eine Unterklasse DebugStack von Stack, die • Im Konstruktor einen Namen des DebugStack erhält, den sie sich in einem Feld merkt. • Beim Aufruf des Konstruktors eine Nachricht ausgibt: „DebugStack xyz initialisiert“ • Die Methoden push und pop überschreibt, so daß diese auch Debugging Nachrichten ausgeben: „String blabla auf DebugStack xyz geschoben“ bzw. „String blabla von DebugStack xyz genommen“ Benutze im Hauptprogramm nun zwei DebugStack Objekte! PSWT 2006 – 24. Oktober 2006 – p.21/26