252-0027
Einführung in die Programmierung
6.0 Objekte
Thomas R. Gross
Department Informatik ETH Zürich
Copyright (c) Pearson 2013 and Thomas R Gross 2016, 2017 All rights reserved.
Uebersicht
6.3 Parameter (Reference Type) 6.4 Konstruktoren
6.5 Noch ein Beispiel (Methoden) 6.6 Namesräume
6.7 static Methoden und Variablen 6.8 Module
Copyright (c) Pearson 2013. and Thomas Gross 2016 All rights reserved.
4
Point Klasse, Version 2
public class Point { int x;
int y;
public String toString() {
return "( " + x + ", " + y + " )";
}
public double distance() { // distance to (0, 0)
return Math.sqrt(x*x + y*y);
} } ...
Reference Semantics
§ Reference Variables die auf Objektexemplare
verweisen folgen den Reference Semantics Regeln
Point p1 = new Point();
p1.x = 3;
p1.y = 2;
Point p2 = p1; // p2.x == 3, p2.y == 2 p2.x = 4; // p2.x == 4, p2.y == 2 // p1.x == 4, p2.y == 2 p1 = null; // p1.x nicht zulaessig
6
9
Point Klasse, Version 2 Fortsetzung
public class Point { int x;
int y;
public String toString() {
return "( " + x + ", " + y + " )";
}
public double distance() { // distance to (0, 0)
return Math.sqrt(x*x + y*y);
}
public double distance(Point other) { // distance to other
return Math.sqrt((x-other.x)*(x-other.x)
+(y-other.y)*(y-other.y));
...}
Parameter Wiederholung
public class Parameter { public static void main
(String[] args) { int i = 1;
mOne(i);
System.out.
println("i = " + i);
}
}
public static void mOne(int x) { System.out.println("x = " + x);
x++;
System.out.println("x = " + x);
}
11
Parameter Wiederholung
public class Parameter { public static void main
(String[] args) { int i = 1;
mOne(i);
System.out.
println("i = " + i);
}
}
public static void mOne(int x) { System.out.println("x = " + x);
x++;
System.out.println("x = " + x);
}
12
x = 1 x = 2 i = 1
Value Semantics
13
main i: 1
mOne
Value Semantics
14
main i: 1
mOne 1
copy
Value Semantics
15
main i: 1
mOne 1
copy
Value Semantics
16
main i: 1
mOne x: 1 1
Value Semantics
17
main i: 1
mOne x: 2
Value Semantics
18
main i: 1
mOne x: 2
Parameter Uebergabe
§ Primitive Types: Kopieren, dann übergeben
§ Ein Buch (oder eine Festschrift) passen nicht in den Umschlag.
§ Buch: int[] book = new int[1000];
§ Festschrift:
class FestSchrift {
String author = "Famous";
int value = 1;
}
Festschrift feS = new FestSchrift(); 19
Parameter
public class Parameter { public static void main
(String[] args) { FS feS = new FS();
mTwo(feS);
System.out.
println("Author = " + feS.author + " " + feS.value);
} }
public static void mTwo(FS x) {
System.out.println("Author = " + x.author + " " + x.value);
x.value++;
x.author = "Nobody";
System.out.println("Author = " + x.author + " " + x.value);
}
20
Parameter
public class Parameter { public static void main
(String[] args) { FS feS = new FS();
mTwo(feS);
System.out.
println("Author = " + feS.author + " " + feS.value);
} }
public static void mTwo(FS x) {
System.out.println("Author = " + x.author + " " + x.value);
x.value++;
x.author = "Nobody";
System.out.println("Author = " + x.author + " " + x.value);
}
21
Author = Famous 1 Author = Nobody 2 Author = Nobody 2
Reference Semantics
22
main feS:
mTwo
Reference Semantics
23
main feS:
mTwo Famous
1
Reference Semantics
24
mTwo Famous
1
KF 456 ….
copy main
feS:
Reference Semantics
26
feS
Famous 1
Reference Semantics
27
mTwo Famous
1
KF 456 ….
copy main
feS:
Reference Semantics
28
mTwo Famous
1
KF 456 ….
main feS:
Reference Semantics
29
mTwo Famous
1
x:
main feS:
Reference Semantics
30
Nobody 2
x main
feS:
mTwo x:
Reference Semantics
31
mTwo Nobody
main 2
feS: x:
Reference Semantics
§ Ist der Parameter eine Referenzvariable, so wird diese kopiert und an die aufgerufene Methode übergeben
§ Das Argument (in der aufrufenden Methode) und der Parameter (in der aufgerufenen Methode) verweisen beide auf das selbe Objekt.
§ Aenderungen des Objektes sind in der aufrufenden Methode sichtbar
§ Gilt für Exemplare von Klassen und für Arrays
32
Parameter
public class Parameter { public static void main
(String[] args) { FS feS = new FS();
mThree(feS);
System.out.
println("Author = " + feS.author + " " + feS.value);
} }
public static void mThree(FS x) { System.out.println("Author = " +
x.author + " " + x.value);
x = new FS();
x.author = "Hero";
System.out.println("Author = " + x.author + " " + x.value);
}
33
Parameter
public class Parameter { public static void main
(String[] args) { FS feS = new FS();
mThree(feS);
System.out.
println("Author = " + feS.author + " " + feS.value);
} }
public static void mThree(FS x) { System.out.println("Author = " +
x.author + " " + x.value);
x = new FS();
x.author = "Hero";
System.out.println("Author = " + x.author + " " + x.value);
}
34
Author = Famous 1 Author = Hero 1 Author = Famous 1
Reference Semantics
35
mThree Famous
main 1
feS: x:
Reference Semantics
36
mThree Famous
1 Hero
main 1
feS: x:
Reference Semantics
§ Ist der Parameter eine Referenzvariable, so wird diese kopiert und an die aufgerufene Methode übergeben
§ Das Argument (in der aufrufenden Methode) und der Parameter (in der aufgerufenen Methode) verweisen beide auf das selbe Objekt.
§ Aenderungen des Objektes sind in der aufrufenden Methode sichtbar
§ Aenderungen der Referenzvariable sind in der aufrufenden Methode nicht sichtbar
§ Wenn Sie die Bibliothekskarte eines Buches ändern so bleibt das Buch unverändert
37
Java Methodenaufruf
§ In Java werden also Referenzvariable und Variable eines Basistyps immer kopiert.
§ Die Entwickler haben darauf keinen Einfluss.
§ Andere Programmiersprachen erlauben mehr Flexibilität. Für jeden Parameter kann bestimmt werden, wie er übergeben wird.
§ Viele Fehler sind möglich ….
38
Uebersicht
6.3 Parameter (Reference Type) 6.4 Konstruktoren
6.5 Noch ein Beispiel (Methoden) 6.6 Namesräume
6.7 static Methoden und Variablen 6.8 Module
Copyright (c) Pearson 2013. and Thomas Gross 2016 All rights reserved.
39
Konstruktion und Initialisierung von Objekten
§ Der new Operator liefert eine Referenz (einen Verweis) auf ein neues Objekt
§ new class(): Exemplar (Instanz) der Klasse class
§ new class[size]: Array der Länge size für Referenzen auf Exemplare der Klasse class
Vergleiche mit:
§ new int[size]: Array der Länge size für int Werte
Initialisierung von Objekten
§ Bisher waren mehrere Anweisungen nötig, um ein Exemplar einer Klasse zu konstruieren und es zu initialisieren:
Point p = new Point();
p.x = 3;
p.y = 8;
§ (N+1) Anweisungen bei N Attributen
§ Lange Folgen von Anweisungen
§ Leicht etwas zu übersehen
Initialisierung von Objekten
§ Besser wäre es die Werte für die Attribute gleich anzugeben:
Point p = new Point(3, 8); // better!
Person employee = new Person("Paula", 123);
§ Wir können so etwas für viele Arten von Objekten in Java machen.
Konstruktoren
§ Konstruktor (“constructor”): Initialisiert den Zustand eines neuen Objektes.
public type(parameters) { statements;
}
§ Ausgeführt wenn der new Operator ausgeführt wird
§ Es gibt keinen Rückgabewert.
§ Im Rumpf können beliebige Anweisungen auftreten (wie in Methode)
Konstruktoren
§ Ein Konstruktor ist keine Methode
§ Konstruktoren sind optional
§ Wenn eine Klassendefinition keinen Konstruktor enthält, dann stellt Java einen (voreingestellten) default Konstruktor (“default
constructor”) zur Verfügung
§ Der default Konstruktor hat keine Parameter und setzt alle Felder auf Null (entweder 0, 0.0, oder null)
Beispiele von Konstruktoren
public class Point { int x;
int y;
// Constructs a Point at the given x/y location.
public Point(int initialX, int initialY) { x = initialX;
y = initialY;
}
// Methods ...
}
Beispiele von Konstruktoren
public class Person { String name;
int id;
double hourlyRate;
double [] hours;
double [] overtime;
// Constructs a Person with given name and Id public Person(String firstname, int uniqueId) {
name = firstname;
id = uniqueId;
}
// Methods ...
}
Konstruktor
§ Attribute, die nicht in einem Konstruktor auf einen Wert
gesetzt werden, werden auf Null gesetzt (0, 0.0, or null).
§ Beispiel:
public Point (int initialX) { x = initialX;
}
Point p1 = new Point(7);
// p1.y == 0
47
Ausführung eines Konstruktors in Zeitlupe
§ Was passiert wenn dieser Code ausgeführt wird?
Point p1 = new Point(7, 2);
Ausführung eines Konstruktors in Zeitlupe
§ Was passiert wenn dieser Code ausgeführt wird?
Point p1 = new Point(7, 2);
public Point(int initialX, int initialY) { x = initialX;
y = initialY;
}
public void setLocation(int newX, int newY) {
…
x y
p1
Ausführung eines Konstruktors in Zeitlupe
§ Was passiert wenn dieser Code ausgeführt wird?
Point p1 = new Point(7, 2);
public Point(int initialX, int initialY) { x = initialX;
y = initialY;
}
public void setLocation(int newX, int newY) {
…
x 0 y 0
p1
Ausführung eines Konstruktors in Zeitlupe
§ Was passiert wenn dieser Code ausgeführt wird?
Point p1 = new Point(7, 2);
public Point(int initialX, int initialY) { x = initialX;
y = initialY;
}
public void setLocation(int newX, int newY) {
…
x 7 y 0
p1
Ausführung eines Konstruktors in Zeitlupe
§ Was passiert wenn dieser Code ausgeführt wird?
Point p1 = new Point(7, 2);
public Point(int initialX, int initialY) { x = initialX;
y = initialY;
}
public void setLocation(int newX, int newY) {
…
x 7 y 2
p1
Ausführung eines Konstruktors in Zeitlupe
§ Was passiert wenn dieser Code ausgeführt wird?
Point p1 = new Point(7, 2);
public Point(int initialX, int initialY) { x = initialX;
y = initialY;
}
public void setLocation(int newX, int newY) {
…
x 7 y 2
p1
Mehrere Konstruktoren
§ Eine Klasse kann mehrere Konstruktoren haben.
§ Jeder Konstruktor muss eine unverwechselbare Liste von Parametern haben
§ Entscheidend ist dass die Typen der Parameterliste unverwechselbar sind
§ Erlaubt
public Point(int initialX, int initialY) { x=initialX; y=initialY; } public Point(int initialX) {x = nitialX; y = 0;}
§ Nicht erlaubt
public Point(int initialX, int initialY) { x=initialX; y=initialY; } public Point(int a, int b) { x = a; y = b; }
§ Schreiben Sie einen Point Konstructor ohne Parameter der den Punkt mit (0, 0) initialisiert.
// Constructs a new point at (0, 0).
public Point() { x = 0;
y = 0;
}
58
Häufige Fehler in Konstruktoren
1. (Erneute) Deklaration von Attributen als Variable:
public Point(int initialX, int initialY) { int x = initialX;
int y = initialY;
}
§ Jetzt gibt es Variable x und y die nur im Konstruktor bekannt sind.
Diese erhalten einen Wert – aber die Attribute werden nicht modifiziert und bleiben 0.
Häufige Fehler in Konstruktoren
2. Versehentlich für den Konstruktor einen Rückgabewert deklarieren:
public void Point(int initialX, int initialY) { x = initialX;
y = initialY;
}
§ Nicht die Definition eines Konstruktors sondern die Definition einer Methode mit Namen Point
Häufige Fehler mit Konstruktoren
3.) Den parameterlosen default Konstruktor verwenden wenn andere Konstruktoren definiert wurden und kein
parameterloser Konstruktor definiert wurde.
class Point { int x; int y;
public Point(int initialX, int initialY) { … } // methods
}
// in the client
Point p = new Point(); 61
Uebersicht
6.3 Parameter (Reference Type) 6.4 Konstruktoren
6.5 Noch ein Beispiel (Methoden) 6.6 Namesräume
6.7 static Methoden und Variablen 6.8 Module
62
Ein Problem: Teilfolgen finden
§ Gegen sei ein Folge S der Länge n (S0, S1, …, Sn-1) wobei jedes Si aus einem (endlichen) Alphabet gewählt ist.
§ Eine Folge T der Länge m heisst Teilfolge von S, wenn es m aufsteigend sortierte Indizes i0, i1, ..., im-1 gibt so dass Sik = Tk für k = 0, …, (m-1).
§ Beispiel:
§ S = ABCDE, T = ACD: (i0,i1,i2) = (0,2,3)
§ S = ABCDC, T = BDC: (i0,i1,i2) = (1,3,4) 63
Teilfolgen finden
§ Schreiben Sie ein Programm, dass für eine Folge S und eine nicht-negative ganze Zahl j alle Teilfolgen der Länge j von S bestimmt.
64
Beispiele
§ S = abcd, j = 3
abc abd bcd acd
§ S = abcd, j = 5
§ S = abcd, j = 0
leerer String ("")
§ S = accb, j = 2
ac ac ab cc cb cb
65
Teilfolgen finden
§ Folge: als (Java) String dargestellt. Alphabet: Default Alphabet der Java Implementation.
§ nicht-negative ganze Zahl: int
§ Schreiben Sie ein Programm, dass einen String S und eine nicht-negative ganze Zahl j einliest und alle Teilfolgen der Länge j ausgibt.
66
Teilfolgeprobleme
§ Gemeinsame Teilfolgen
§ Längste gemeinsame Teilfolgen
§ Folgen von DNA, RNA, Protein Molekülen …
67
68
69
Rahmen
import java.util.Scanner;
public class Subsequence {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
System.out.print("Input string (no spaces):");
String str = console.next();
System.out.print("Length of subsequences:");
int subseqLength = console.nextInt();
// … unser Programm } // main
} 70
Ansatz
1. Finden von Indexfolgen i0, i1, i2, …, ij-1
a. Alle ausprobieren
b. Zufällige (Index)Folgen generieren
§ Speichern ob schon ausgegeben
§ Neue geben entsprechenden String aus
2. Mit Strings (direkt) arbeiten
§ Indices treten nicht direkt in Erscheinung
73
74
a b c d
Länge 1
75
a b c d
Länge 1
a b c d
76
a b c d
Länge 2
a b c d
77
a b c d
Länge 2 a
a b c d b c d
78
a b c d
Länge 2 a
a b c d b c d
b
a b c d c d
79
a b c d
Länge 2 a
a b c d b c d
b
a b c d c d
c
a b c d d
80
a b c d
Länge 2 a
a b c d b c d
b
a b c d c d
c
a b c d d ab ac ad bc bd cd
81
a b c d e f g h u v w x y z
Länge j
a b c d e f g h u v w x y z a b c d e f g h u v w x y z String Länge s
(gebildet aus diesem Teil von str, einem Prefix von str)
String Länge (s+1) (gebildet aus dem Prefix von str) + g
Brauchen String Länge (j-s) gebildet aus dem Rest
Brauchen String Länge (j-s-1) gebildet aus dem Rest
82
a b c d e
Länge 3
a b c d e a b c d e String Länge 1
(gebildet aus diesem Teil von str, einem Prefix von str)
String Länge 2 (gebildet aus dem Prefix von str) + b
Brauchen String Länge 2 gebildet aus dem Rest
Brauchen String Länge 1 gebildet aus dem Rest
a b c d e String Länge 3
(gebildet aus dem Prefix von str) + c
Brauchen String Länge 0 gebildet aus dem Rest
Lösungs(anfang)
§ Wenn wir einen String P haben und noch 0 Zeichen (aus dem unverarbeiteten Rest) dazu fügen müssen, dann haben wir ein Teilfolge mit j Zeichen gefunden.
§ Wir fangen an mit P dem leeren String, t = j (Anzahl Zeichen) die wir noch brauchen, und der Rest ist der Eingabestring.
83
Lösungs(anfang)
§ Wenn wir einen String P haben und noch 0 Zeichen (aus dem unverarbeiteten Rest) dazu fügen müssen, dann haben wir ein Teilfolge mit j Zeichen gefunden.
§ Wir fangen an mit P dem leeren String, t = j (Anzahl Zeichen) die wir noch brauchen, und der Rest ist der Eingabestring.
§ Wenn wir einen String P der Länge s haben (s<j, d.h. wir
brauchen noch j-s Buchstaben aus dem Rest) dann nehmen wir den 1. Buchstaben des Rests, konkatenieren ihn mit P und machen weiter (d.h. brauchen noch j-s-1 Buchstaben, neuer Rest ist der alte Rest ohne den 1. Buchstaben). 84
Lösungs(anfang)
§ Wenn wir einen String P der Länge s haben (s<j, d.h. wir
brauchen noch j-s Buchstaben aus dem Rest) dann nehmen wir den 1. Buchstaben des Rests, konkatenieren ihn mit P und machen weiter (d.h. brauchen noch j-s-1 Buchstaben, neuer Rest ist der alte Rest ohne den 1. Buchstaben).
§ Wenn der Rest leer ist dann können wir mit diesem String P nicht weiter arbeiten
85
86
a b c
Länge 4
a b c a b c String Länge 1
String Länge 2
Brauchen String Länge 3 gebildet aus dem Rest "bc"
Brauchen String Länge 2 gebildet aus dem Rest "c"
a b c
String Länge 3 Brauchen String Länge 1
gebildet aus dem Rest ""
87
a b c d e f g h u v w x y z
Länge j
a b c d e f h u v w x y z a b c d e f g h u v w x y z String Länge s
(gebildet aus diesem Teil von str, einem Prefix von str)
String Länge s
Brauchen String Länge (j-s)
gebildet aus dem Rest "g h u … "
Brauchen String Länge (j-s)
gebildet aus dem Rest "h u v … "
a b c d e
Länge 3
a c d e a b c d e String Länge 1
(gebildet aus diesem Teil von str, einem Prefix von str)
String Länge 1
Brauchen String Länge 2 gebildet aus dem Rest
Brauchen String Länge 2 gebildet aus dem Rest
Lösung (weiter)
Wenn wir einen String P der Länge s haben (s<j, d.h. wir
brauchen noch j-s Buchstaben aus dem Rest, Rest nicht leer)
1. Wir nehmen den 1. Buchstaben des Rests, konkatenieren ihn mit P und machen weiter (d.h. brauchen noch j-s-1
Buchstaben, neuer Rest ist der alte Rest ohne den 1.
Buchstaben)
2. Wir finden die j-s Buchstaben im Rest ohne den 1.
Buchstaben (d.h., wir brauchen immer noch j-s Buchstaben, neuer Rest ist der alte Rest ohne den 1. Buchstaben)
89
90
Lösung
import java.util.Scanner;
public class Subsequence {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
System.out.print("Input string (no spaces):");
String str = console.next();
System.out.print("Length of subsequences:");
int subseqLength = console.nextInt();
findSubSequence("", str, subseqLength) } // main
91
public static void findSubSequence(String prefix, String remaining, int target) {
// target: characters needed to reach desired subsequence length
if (target == 0) {
System.out.println(prefix);
return;
}
if (!remaining.isEmpty()) {
findSubSequence(prefix + remaining.charAt(0),
remaining.substring(1), target-1);
findSubSequence(prefix, remaining.substring(1), target);
}
} //findSubSequence 92
public static void findSubSequence(String prefix, String remaining, int target) {
// target: characters needed to reach desired subsequence length
if (target == 0) {
System.out.println(prefix);
return;
}
if (!remaining.isEmpty()) {
findSubSequence(prefix + remaining.charAt(0),
remaining.substring(1), target-1);
findSubSequence(prefix, remaining.substring(1), target);
}
} //findSubSequence 93
public static void findSubSequence(String prefix, String remaining, int target){
for (int i=0; i<prefix.length(); i++) { System.out.print(" ");
}
System.out.println("Prefix \"" + prefix + "\" Remaining \""
+ remaining + "\" Target=" + target);
if (target == 0) {
System.out.println(prefix);
return;
}
if (!remaining.isEmpty()) {
findSubSequence(prefix + remaining.charAt(0), remaining.substring(1), target-1);
findSubSequence(prefix, remaining.substring(1), target);
}
} 94
mit Log/Trace
Input string (no spaces):abcd Length of subsequences:3
input = abcd 3
Prefix "" Remaining "abcd" Target=3 Prefix "a" Remaining "bcd" Target=2
Prefix "ab" Remaining "cd" Target=1 Prefix "abc" Remaining "d" Target=0 abc
Prefix "ab" Remaining "d" Target=1 Prefix "abd" Remaining "" Target=0 abd
Prefix "ab" Remaining "" Target=1 Prefix "a" Remaining "cd" Target=2
Prefix "ac" Remaining "d" Target=1 Prefix "acd" Remaining "" Target=0 acd
Prefix "ac" Remaining "" Target=1 Prefix "a" Remaining "d" Target=2
Prefix "ad" Remaining "" Target=1 95
Log
Prefix "a" Remaining "" Target=2 Prefix "" Remaining "bcd" Target=3
Prefix "b" Remaining "cd" Target=2 Prefix "bc" Remaining "d" Target=1
Prefix "bcd" Remaining "" Target=0 bcd
Prefix "bc" Remaining "" Target=1 Prefix "b" Remaining "d" Target=2
Prefix "bd" Remaining "" Target=1 Prefix "b" Remaining "" Target=2 Prefix "" Remaining "cd" Target=3
Prefix "c" Remaining "d" Target=2 Prefix "cd" Remaining "" Target=1 Prefix "c" Remaining "" Target=2 Prefix "" Remaining "d" Target=3
Prefix "d" Remaining "" Target=2 Prefix "" Remaining "" Target=3
96