• Keine Ergebnisse gefunden

252-0027 Einführung in die Programmierung 7.0 Arbeiten mit Objekten und Klassen

N/A
N/A
Protected

Academic year: 2022

Aktie "252-0027 Einführung in die Programmierung 7.0 Arbeiten mit Objekten und Klassen"

Copied!
62
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

252-0027

Einführung in die Programmierung

7.0 Arbeiten mit Objekten und Klassen

Thomas R. Gross

Department Informatik ETH Zürich

Copyright (c) Pearson 2013. and Thomas Gross 2016 All rights reserved.

(2)

Uebersicht

7.1 Initialisierung

§ Variable in Methoden

§ Variable (Attribute) in Klassen

7.2 Listen als Beispiel

§ Warum kopieren wir in einem Program Referenzen auf Objekte oder Arrays?

Copyright (c) Pearson 2013 and Thomas Gross 2016.

All rights reserved. 2

(3)

Eine Klasse für Knoten einer Liste

public class ListNode { int data;

ListNode next;

§ Jeder Knoten der Liste speichert:

}

§ Den Wert einer ganzen (int) Zahl

§ Einen Verweis auf einen anderen Listenknoten

§ ListNodes können zu einer Kette verbunden (“linked”) wer- den um eine Menge oder Liste von Werten zu speichern.

data next 42

data next -3

data next 17

data next 9 null

(4)

5

(5)

Probleme

§ Wie könnten wir den Knoten an Anfang entfernen?

int top = list.removeFront(); //??

§ Gewünscht:

§ Entfernen ist einfach aber wie kann die Referenzvariable list auf das (neue) erste Element verweisen?

6

data next 10

data next

list 20 data next

40

list data next

20

data next 40

(6)

Probleme

§ Was passiert wenn wir eine beliebige Referenzvariable current verwenden?

int someValue = current.removeFront(); //??

§ Gewünscht:

§ Aber wie erreichen wir den Vorgängerknoten?

7

data next 10

data next

list 20 data next

40

list data next 10

data next 40

current

(7)

Eine Klasse LinkedIntList

§ ListNodes sollen nicht von Klienten direkt verändert werden.

§ Also entwickeln wir eine Klasse die die Knoten versteckt:

LinkedIntList.

front LinkedIntList

ListNode ListNode ListNode

data next 42

data next -3

data next 17

(8)

Eine Klasse LinkedIntList

§ Klienten arbeiten mit LinkedIntList, nicht mit ListNode Objekten.

§ Wir können die Elemente numerieren (von 0 an)

front LinkedIntList

ListNode ListNode ListNode

data next 42

data next -3

data next 17

element 0 element 1 element 2

(9)

§ Hat die Methoden:

§ add, get, indexOf, remove, size, toString

§ Die Liste ist als Kette von Knoten intern implementiert

§ Das LinkedIntList Objekt enthält eine Referenz auf das erste Element in front

§ null im next Attribut signalisiert Ende der Liste

§ Hat front den Wert null so ist die Liste leer

front add(value)

add(index, value) indexOf(value) remove(index) size()

toString() LinkedIntList

ListNode ListNode ListNode

data next 42

data next -3

data next 17

element 0 element 1 element 2

(10)

LinkedIntList Klasse v1

public class LinkedIntList { private ListNode front;

public LinkedIntList() { front = null;

}

// methods }

front = LinkedIntList

(11)

Die add Methode

// Adds the given value to the end of the list.

public void add(int value) { ...

}

§ Wie wollen wir einen neuen Knoten am Ende hinzufügen?

§ Sind die Werte in der Liste vor diesem Schritt wichtig?

front =

data next 42

data next -3

data next 17

element 0 element 1 element 2

(12)

Ein Element in eine leere Liste hinzufügen

§ Bevor 20 hinzugefügt wird: Danach:

§ Wir müssen einen Knoten erstellen und an die Liste anhängen.

front = front =

data next 20

element 0

(13)

Die add Methode, 1. Versuch

// Adds the given value to the end of the list.

public void add(int value) { if (front == null) {

// adding to an empty list front = new ListNode(value);

} else {

// adding to the end of an existing list

...

} }

(14)

§ Bevor 20 am Ende hinzugefügt wird :

§ Danach:

front =

data next 42

data next -3

front =

data next 42

data next 20

element 0 element 2

element 0 element 1

An eine nicht-leere Liste anhängen

data next -3

element 1

(15)

data next -3

Vorsicht an der Kante!

§ Um ein Element zur Liste hinzuzufügen (oder zu von der Liste zu entfernen) müssen wir das next Attribut des vorherigen Knotens modifizieren.

§ Wie durchlaufen wir eine Liste?

§ Was für einen Typ muss current haben? ListNode

front =

data next 42

element 0 element 1

(16)

data next -3

Vorsicht an der Kante!

§ Um ein Element zur Liste hinzuzufügen (oder zu von der Liste zu entfernen) müssen wir das next Attribut des vorherigen Knotens modifizieren.

§ Worauf sollte current verweisen wenn wir 20 am Ende einfügen wollen?

§ Welcher Loop Test lässt uns an dieser Stelle anhalten?

front =

data next 42

element 0 element 1

(17)

Die add Methode

// Adds the given value to the end of the list.

public void add(int value) { if (front == null) {

// adding to an empty list front = new ListNode(value);

} else {

// adding to the end of an existing list ListNode current = front;

while (current.next != null) { current = current.next;

}

current.next = new ListNode(value);

} }

(18)

Implementation von get

// Returns value in list at given index.

// 0 <= index < size()

public int get(int index) { ...

}

§ Implementieren Sie die get Methode.

front =

data next 42

data next -3

data next 17

element 0 element 1 element 2

(19)

Die get Methode

// Returns value in list at given index.

// 0 <= index < size()

public int get(int index) { ListNode current = front;

for (int i = 0; i < index; i++) { current = current.next;

}

return current.data;

}

(20)

Implementation von add (index)

// Inserts the given value at the given index.

public void add(int index, int value) { ...

}

§ Implementieren Sie diese Variante der add Methode.

front =

data next 42

data next -3

data next 17

element 0 element 1 element 2

(21)

Die 2. Variante der add Methode

// Inserts the given value at the given index.

// 0 <= index <= size()

public void add(int index, int value) { if (index == 0) {

// adding to an empty list

front = new ListNode(value, front);

} else {

// inserting into an existing list ListNode current = front;

for (int i = 0; i < index - 1; i++) { current = current.next;

}current.next = new ListNode(value, current.next);

} }

(22)

Element entfernen: remove

// Removes and returns the list's first value.

public int remove() { ...

}

§ Wie entfernt man den ersten Knoten einer Liste?

§ Ist der Inhalt der Liste wichtig wenn wir den ersten Knoten entfernen wollen?

(23)

Entfernen des ersten Elements

§ Vor dem Entfernen des ersten Elements:

§ Nachdem ein Element entfernt wurde: Nachdem 2 Elemente … :

front =

data next 20

front =

data next 42

data next 20

element 0 element 1

element 0

front =

(24)

remove Methode

// Removes and returns the first value.

// List must not be empty.

public int remove() {

if (front == null) { System.exit(-1);

}

int result = front.data;

front = front.next;

return result }

(25)

Eine weitere remove Methode

// Removes value at given index from list.

// Precondition: 0 <= index < size public void remove(int index) {

...

}

§ Wie können wir ein beliebiges Element der Liste entfernen?

§ Ist der Inhalt der Liste wichtig wenn wir einen Knoten entfernen wollen?

(26)

Entfernen eines Elementes

§ Vor dem Entfernen des Elements mit Index 1:

§ Danach:

front =

data next 20

front =

data next 42

data next -3

data next 20

element 0 element 1 element 2

element 0 element 1

data next 42

(27)

Entfernen des Elements mit Index 0

§ Vor Entfernen des Elements mit Index 0:

§ Danach:

front =

data next -3

data next 20

front =

data next 42

data next -3

data next 20

element 0 element 1 element 2

element 0 element 1

(28)

Entfernen des einzigen Elementes

§ Davor: Danach:

§ Wir müssen das front Attribut auf null setzen (so dass es nicht auf einen ListNode verweist)

§ Ist das ein Sonderfall den wir im Programm behandeln müssen?

front front =

data next 20

element 0

(29)

remove Methode (Variante 2)

// Removes value at given index from list.

// Precondition: 0 <= index < size() public void remove(int index) {

if (index == 0) {

// special case: removing first element front = front.next;

} else {

// removing from elsewhere in the list ListNode current = front;

for (int i = 0; i < index - 1; i++) { current = current.next;

}current.next = current.next.next;

} }

(30)

LinkedIntList Klasse v2

public class LinkedIntList { private ListNode front;

public LinkedIntList() { front = null;

}

public void add (int value) { … }

public void add (int index, int value) { … } public void remove() { … }

public void remove(int index) { … } }

front = LinkedIntList

(31)

Namen von Methoden

§ In einer Klasse können verschiedene Methoden den selben Namen haben

public void add (int value) { … }

public void add (int index, int value) { … }

§ Die Typen der Parameter müssen unterschiedlich sein

public void add (int value) { … }

public void add (int index) { … } // not OK

35

(32)

36

String

toString muss natuerlich einen String zurueckgeben!

(33)

Uebung

§ Schreiben Sie eine Methode addSorted die den Wert einer ganzen Zahl als Parameter akzeptiert und diesen Wert in die sortierte Liste an der

richtigen Position einfügt (d.h., die Liste ist auch danach sortiert).

§ Vor addSorted(17) :

§ Nach addSorted(17) :

front = data next

-4

data next 8

data next 22

element 0 element 1 element 2

front = data next

-4

data next 17

data next 22

element 0 element 2 element 3

data next 8

element 1

(34)

Der “Normalfall”: irgendwo einfügen

§ Einfügen eines Elementes ”im Inneren” der Liste:

addSorted(17)

§ Welche Verweise (Referenzen) müssen geändert werden?

§ Was für eine Schleife bietet sich an?

§ Wann sollte die Schleife terminieren?

front = data next

-4

data next 8

data next 22

element 0 element 1 element 2

(35)

Erster Versuch

§ Fehlerhafte Schleife:

ListNode current = front;

while (current.data < value) { current = current.next;

}

§ Wo ist der Fehler?

§ Die Schleife endet zu spät um die Liste korrekt zu verändern.

front = data next

-4

data next 8

data next 22

element 0 element 1 element 2

current

(36)

Idee: vorausschauen

§ Korrekte Schleife:

ListNode current = front;

while (current.next.data < value) { current = current.next;

}

§ Diesmal hört die Schleife an der richtigen Stelle auf.

front = data next

-4

data next 8

data next 22

element 0 element 1 element 2

current

(37)

Spezialfall 1: Hinzufügen am Ende

§ Hinzufügen am Ende der Liste:

addSorted(42)

Exception in thread "main": java.lang.NullPointerException

§ Warum gibt es eine Exception?

§ Was können wir ändern um diesen Fall richtig zu behandeln?

front = data next

-4

data next 8

data next 22

element 0 element 1 element 2

(38)

Mehrere Tests für die Schleife

§ A correction to our loop:

ListNode current = front;

while (current.next != null &&

current.next.data < value) { current = current.next;

}

§ Wir müssen prüfen ob next den Wert null hat bevor wir das data Attribut des Knotens (d.h., next.value) prüfen

front = data next

-4

data next 8

data next 22

element 0 element 1 element 2

current

(39)

Spezialfall 2: Hinzufügen am Anfang

§ Einfügen am Anfang der Liste:

addSorted(-10)

§ Was passiert jetzt in unserem Programm?

§ Wie können wir diesen Fehler beheben?

front = data next

-4

data next 8

data next 22

element 0 element 1 element 2

(40)

Hinzufügen am Anfang

§ Eine weitere Verbesserung des Programms

if (value <= front.data) {

// insert at front of list

front = new ListNode(value, front);

} else {

// insert in middle of list ListNode current = front;

while (current.next != null &&

current.next.data < value) { current = current.next;

} }

§ Kann diese Methode jetzt alle möglichen Fälle behandeln?

(41)

Spezialfall 3: Leere Liste

§ Hinzufügen (am Anfang) zu einer leeren Liste:

addSorted(42)

§ Was passiert jetzt in unserem Programm?

§ Wie können wir diesen Fehler beheben?

front =

(42)

Endgültige Version

// Adds given value to list in sorted order.

// Precondition: Existing elements are sorted public void addSorted(int value) {

if (front == null || value <= front.data) { // insert at front of list

front = new ListNode(value, front);

} else {

// insert in middle of list ListNode current = front;

while (current.next != null &&

current.next.data < value) { current = current.next;

} }

}

(43)

(Verknüpfte) Liste vs. Array

§ Algorithmus um die Werte der Liste auszugeben:

ListNode front = ...;

ListNode current = front;

while (current != null) {

System.out.println(current.data);

current = current.next;

}

§ Algorithmus um die Werte des Arrays auszugeben:

int[] a = ...;

int i = 0;

while (i < a.length) {

System.out.println(a[i]);

i++;

}

(44)

Diskussion Liste vs. Array

§ Vorteil Array

§ Konstante Zugriffszeit

§ Vorteil Liste

§ Grösse flexibel

(45)

Ein paar Fragen

§ Was ist der Unterschied zwischen einer LinkedIntList und einem ListNode?

§ Was ist der Unterschied zwischen einer leeren und einer null Liste?

§ Wie können wir jede von ihnen konstruieren/generieren

(46)

Ein paar Fragen

§ Die Attribute von ListNode sind nicht private? Ist das guter oder schlechter Stil?

§ Welchen Effekt hat dieses Codesegment auf eine LinkedIntList values?

ListNode current = values.front;

current = null;

(47)

Antworten

§ Eine Liste besteht aus 0 oder mehr Knoten.

§ Jeder Knoten ist ein ListNode Objekt

§ Jeder Knoten enthält einen einzigen (int) Wert.

§ null Liste:

LinkedIntList list = null;

leere Liste:

LinkedIntList list = new LinkedIntList();

(48)

Antworten

§ Das kann man vertreten da LinkedIntList der einzige Klient von ListNode ist

§ Andere Programme manipulieren nicht die ListNode Objekte sondern arbeiten mit Methoden der LinkedIntList Klasse.

§ Es gibt in Java noch bessere Möglichkeiten, solche Klassen zu organisieren, aber die lernen wir erst später kennen.

§ Diese Zuweisungen ändern die Liste nicht. Die Liste kann nur auf folgende Weise verändert werden:

§ Aendern des front Attributes.

§ Aendern des next Verweises auf einen Knoten in der Liste

§ (Aendern des data Attributes eines Knotens)

(49)

Andere Operationen für Listen

§ Implementieren Sie weitere Methoden für LinkedIntList:

§ size

§ isEmpty

§ clear

§ toString

§ indexOf

§ contains

§ Deklarieren Sie ein size Attribut so dass die Anzahl Knoten schnell zurückgegeben werden kann.

(50)

252-0027

Einführung in die Programmierung 8.0 Vererbung

Thomas R. Gross

Department Informatik ETH Zürich

Copyright (c) Pearson 2013 and Thomas Gross 2016 All rights reserved.

(51)

Software Entwicklung

§ Programmieren ist anspruchsvoll

§ Es ist leicht Fehler zu machen

§ LinkedIntList Aufgaben

§ Wir würden gerne Software wiederverwenden

§ Auf früheren Lösungen aufbauen

§ Von LinkedIntList zu DoubleLinkedIntList

§ Von LinkedIntList zu LinkedBooleanList, LinkedPersonList, ….

56

(52)

Software Entwicklung

§ Programmieren ist anspruchsvoll

§ Es ist leicht Fehler zu machen

§ LinkedIntList Aufgaben

§ Wir würden gerne Software wiederverwenden

§ Auf früheren Lösungen aufbauen

§ Von LinkedIntList zu DoubleLinkedIntList

§ Von LinkedIntList zu LinkedBooleanList, LinkedPersonList, ….

58

(53)

Knoten einer doppelt verknüpften Liste

public class DllNode { int data;

DllNode next;

DllNode prev;

§ Jeder Knoten der Liste speichert:

}

§ Den Wert einer ganzen (int) Zahl

§ Einen Verweis auf einen Vorgänger Listenknoten

§ Einen Verweis auf einen Nachfolger Listenknoten

prev data next 42

prev data next -3

prev data next 17

prev data next 9

(54)

Doppelt verknüpfte Liste

public class DoubleLinkedIntList { private DllNode front;

private DllNode tail;

// methods }

60 front

tail

DoubleLinkedIntList

DllNode DllNode DllNode

element 0 element 1 element 2

prev data next -3

prev data next 17

prev data next 9

(55)

Uebersicht

§ 8.0 Neue Klassen aus existierendem Klassen

§ 8.1 Konstruktoren

§ 8.2 Selektiv Verhalten (von Objekten) festlegen

61

(56)

Spital Beispiel

§ Gemeinsame Regeln für alle Angestellten: Arbeitszeit, Urlaub, Sozialleistungen, Fortbildung, Pflichtenheft, …

§ Alle Angestellten besuchen eine gemeinsame Orientierungveranstal- tung um die für alle gültigen Regeln des Krankenhauses zu erhalten

§ Verhalten im Notfall, professionelles Verhalten, Lohnfortzahlung im Krankheitsfall, …

§ Alle Angestellten erhalten das 20-seitige Handbuch, das die Arbeitsverhältnisse im Spital regelt

§ Aber …

(57)

§ Aber jede Abteilung hat noch ihre eigenen Regeln

§ Angestellte erhalten ein weiteres Handbuch (mit 1-5 Seiten) für die Regeln, die für ihre Abteilung gelten

63

§ Das Zusatzhandbuch enthält weitere Regeln und ändert oder erweitert Regeln aus dem (allgemeinen) Spitalregelwerk.

Angestellten Handbuch 20 Seiten

Arzt/Aerztin Handbuch

25 Seiten FaGe (Pflege) Handbuch

22 Seiten Adminstrator/in

Handbuch 21 Seiten

OP-Fachkraft Handbuch 25 Seiten

(58)

Organisation der Regeln

§ Warum wollen wir nicht je ein Handbuch für Aerzte/innen (25 Seiten), eines für FaGe (22 Seiten), eines für Administratoren (21 Seiten) und eines für OP-Fachkräfte (25 Seiten) haben?

§ Vorteile wenn wir die Handbücher aufteilen :

§ Anpassungen: Nur eine Stelle muss geändert werden, wenn sich die allgemeinen Regeln ändern.

§ Lokalitätsprinzip: Schneller Ueberblick über die Regeln die nur für Aerzte/innen gelten.

(59)

Was wir aus dem Beispiel mitnehmen

§ Allgemeine Regeln sind sinnvoll (das 20-seitige allgemeine Handbuch).

§ Einzelne Gruppen brauchen evtl. Zusatzregeln die nur für diese Abteilung gelten

§ Die Gruppenregeln haben Vorrang vor den allgemeinen Regeln

§ Die Gruppenregeln können evtl. allgemeine Regeln ausser Kraft setzen.

65

(60)

Regeln für Angestellte

§ Hier ist ein Satz von Regeln der für Angestellte des Krankenhauses gilt:

§ Die Arbeitszeit ist 42 Stunden pro Woche.

§ Angestellte erhalten einen Basislohn von 80’000 sFr/Jahr, bis auf OP-Fachkräfte die 10’000 sFr/Jahr extra erhalten, und Administratoren/-innen, die 5’000

sFr/Jahr extra erhalten.

§ Angestellte haben 4 Wochen Urlaub pro Jahr, bis auf Aerzte/innen, die eine Woche extra (also insgesamt 5 Wochen) bekommen

§ Um einen Urlaub zu beantragen sollten Angestellte ein grünes Formular verwenden, bis auf Aerzte/innen, die ein gelbes Formular brauchen.

68

(61)

Aufgaben und Fähigkeiten der Angestellten

§ Jede Art von Angestellten spielt im Spitalbetrieb eine bestimmte Rolle

§ Aerzte/innen behandeln Patienten (untersuchen und stellen eine Diagnose).

§ Administratoren verarbeiten Rechnungen.

§ FaGe pflegen Patienten auf einer Station (müssen also einer Station zugeteilt sein, für einen bestimmten Zeitraum)

§ OP-Fachkräfte managen den OP-Saal.

§ Wir wollen jetzt ein System erstellen, das die Spitaldirektion bei der Einsatzplanung, Rechnungsstellung etc unterstützt

§ Für jede/r Angestellte/n gibt es ein Exemplar einer Klasse mit der wir planen/verwalten können

69

(62)

Eine Klasse für Angestellte ( Angestellte ” )

// A class to represent employees in general (20-page manual).

public class Angestellte { public int getHours() {

return 42; // works 42 hours / week }

public double getSalary() {

return 80000.0; // sFr 80,000.00 / year }

public int getVacationDays() {

return 20; // 4 weeks paid vacation, not including weekends }

public String getVacationForm() {

return ”green"; // use the green form }

}

Referenzen

ÄHNLICHE DOKUMENTE

§ Programm: Folge von Anweisungen, die von einem Computer ausgeführt werden (können).. § Programm realisiert

§ Eine Referenzvariable (“reference type variable”, Variable eines Referenztyps) erlaubt den Zugriff auf einen Array (ein Objekt)..

§ Alle Methoden einer Klasse können auf eine static Variable zugreifen. § Gemeinsame (&#34;shared&#34;) Variable für

§ Um ein Element zur Liste hinzuzufügen müssen wir das next Attribut des vorherigen Knotens modifizieren?.

§ Wenn eine Methode einen Parameter erwartet dann muss dieser auch übergeben werden. printPunkte(); // ERROR: parameter value

!  Wenn eine Variable als Operand in einer Zuweisung erscheint dann wird der Array nicht kopiert sondern beide Variable beziehen sich nun (verweisen nun) auf den selben Array..

§ Variable, die in einer Methode deklariert sind, müssen einen Wert haben, bevor sie als Operand oder Parameter.. verwendet

§ ListNode s können zu einer Kette verbunden (“linked”) wer- den um eine Menge oder Liste von Werten zu