Darstellung von Information

Download Report

Transcript Darstellung von Information

Konzepte objektorientierter
Programmierung
Klaus Becker
2009
2
Objektorientierung
"Objektorientierung
ist die derzeitige Antwort
auf die gestiegene Komplexität
der Softwareentwicklung."
Oestereich: Objektorientierte Software-Entwicklung
3
Teil 1
Objekte
4
Verwaltung von Bankkonten
Ziel ist es, ein System zur Verwaltung von Bankkonten zu entwickeln. Dieses System soll recht
einfach gestaltet werden, um es leicht durchschaubar zu halten. Aus diesem Grund werden
wir auf viele Aspekte eines realen Bankkontenverwaltungssystem verzichten.
S
Konto-Nr.234126
Freunde des Burggymnasiums
Kontoauszug
Blatt 342
Datum
Erläuterung
01.07.2009
Miete der Fruchthalle - Sommerkonzert
08.07.2009
Spende eines ehemaligen Schülers
10.07.2009
Zuschuss zum Whiteboard
Kontostand in EUR, 11.07.2009
Betrag
450.00 1000.00 +
800.00 -
2130.00 +
Verwaltung von Bankkonten
5
Wesentliche zu verwaltende Daten erkennt man auf einem Kontoauszug.
Kontonummer
Kontoinhaber
S
Konto-Nr.234126
Freunde des Burggymnasiums
Kontoauszug
Blatt 342
Datum
Erläuterung
Betrag
auszahlen
01.07.2009
Miete der Fruchthalle - Sommerkonzert
08.07.2009
Spende eines ehemaligen Schülers
10.07.2009
Zuschuss zum Whiteboard
Kontostand in EUR, 11.07.2009
450.00 1000.00 +
800.00 -
2130.00 +
einzahlen
auszahlen
Kontostand
Ein Bankkonto hat eine bestimmte Kontonummer (und einen Kontoinhaber - von dem wir
vorerst einmal absehen). Ein Bankkonto hat zudem einen bestimmten Stand - das ist der
Geldbetrag, der aktuell auf dem Konto verfügbar ist. Von einem Bankkonto kann man
Geldbeträge auszahlen, man kann aber Geldbeträge auf ein Konto einzahlen.
Objektorientierter Modellierungsansatz
6
So wie die zu verwaltende Welt aus Objekten - hier Konten - besteht,
so soll das Verwaltungssystem aus Softwareobjekten aufgebaut
werden.
Softwareobjekt
S
Konto-Nr.234126
Freunde des Burggymnasiums
Kontoauszug
Blatt 342
Datum
Erläuterung
01.07.2009
Miete der Fruchthalle - Sommerkonzert
08.07.2009
Spende eines ehemaligen Schülers
10.07.2009
Zuschuss zum Whiteboard
Kontostand in EUR, 11.07.2009
Betrag
450.00 1000.00 +
800.00 -
2130.00 +
7
Softwareobjekt in Aktion
Wenn man das Programm konto.py ausführt, dann lässt sich
folgender Python-Dialog führen. Probiere das einmal aus.
>>> konto = Konto(234126)
>>> konto.nr
234126
>>> konto.stand
0
>>> konto.stand = 2380.0
>>> konto.stand
2380.0
>>> konto.auszahlen(450.0)
>>> konto.stand
1930.0
>>> konto.einzahlen(1000.0)
>>> konto.stand
2930.0
>>> konto.auszahlen(800.0)
>>> konto.stand
2130.0
8
Objekte
Ein Objekt ist eine Einheit, die Daten mit
Hilfe von Attributen verwalten und
Operationen zur Verarbeitung der
verwalteten Daten mit Hilfe von Methoden
ausführen kann.
Objekt
Attribute sind - an Objekte gebundene Variablen zur Verwaltung von Daten. Diese
entsprechen in der Regel den Eigenschaften
der betreffenden Objekte.
Methoden sind - an Objekte gebundene Prozeduren oder Funktionen zur
Verarbeitung von Daten. Diese Methoden
werden ausgeführt, wenn das betreffende
Objekt Operationen ausführt.
Ein Objekt befindet sich stets in einem
bestimmten Zustand. Der aktuelle
Objektzustand wird durch die aktuellen
Werte der Attribute festgelegt.
Attribute Attributwerte
Ausführung
einer Methode
Objektdiagramm
9
Zugriff auf Attribute:
objekt.attribut
Objekte
Objekt
konto.stand = 2380.0
Aktivierung von Methoden:
objekt.methode
konto.einzahlen(1000.0)
Attribute Attributwerte
Ausführung
einer Methode
Übungen
10
Aufgabe 1 (siehe www.inf-schule.de 1.12.1.4)
Lade die Datei wuerfel.txt herunter (benenne sie in wuerfel.py um) und führe einen PythonDialog analog zum folgenden:
>>>
>>>
1
>>>
>>>
6
w = Wuerfel()
w.augen
w.werfen()
w.augen
(a) Was leistet das Attribut augen des Objekts w, was die Methode werfen()?
(b) Beschreibe den gezeigten Ablauf mit Hilfe von Objektdiagrammen.
11
Teil 2
Klassen
12
Ein Bauplan für Konto-Objekte
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
self.stand = 0
def einzahlen(self, betrag):
self.stand = self.stand + betrag
def auszahlen(self, betrag):
# ...
>>> k1 = Konto(5)
>>> k1.nr
5
>>> k1.stand
0
>>> k1.einzahlen(100.0)
>>> k1.stand
100.0
Aufgabe 1:
Analysiere diese Klassendeklaration und ergänze den fehlenden Teil #
....
Überprüfen kannst du deinen Lösungsvorschlag, indem du die
Klassendeklaration unter einem geeigneten Namen (z. B. konto.py)
abspeicherst und ausführst. Wenn du alles richtig gemacht hast, dann
sollte z. B. der oben gezeigte Python-Dialog möglich sein.
13
Ein Bauplan für Konto-Objekte
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
self.stand = 0
>>>
>>>
>>>
>>>
k1 = Konto(5)
k1.einzahlen(1000.0)
k2 = Konto(8)
...
def einzahlen(self, betrag):
self.stand = self.stand + betrag
def auszahlen(self, betrag):
# ...
Aufgabe 2:
Versuche auch einmal, mehrere Konto-Objekte zu erzeugen.
Überweise mit passenden Methoden 500.0 (Euro) vom Konto mit der
Kontonummer 5 auf das Konto mit der Kontonummer 8.
14
Klassen
Eine Klasse ist ein Bauplan für Objekte.
Dieser Bauplan legt genau fest, welche
Attribute die zu konstruierenden Objekte
haben sollen und welche Methoden sie
ausführen können sollen.
Ein Objekt (als Exemplar einer Klasse) ist
eine Einheit, die nach dem Bauplan der
zugeordneten Klasse erzeugt wurde. Ein
Objekt verfügt somit über die Attribute, die
in der Klasse festgelegt sind. Diesen
Attributen können - im Unterschied zur
Klasse - Attributwerte zugewiesen werden.
Ein Objekt kann zudem sämtliche Methoden
der Klasse ausführen. Ausgenommen bleibt
hier nur die Methode, deren Name mit dem
Klassennamen übereinstimmt (s. u.).
Objekte können mit Namen versehen
werden, über die sie dann gezielt
angesprochen werden können.
Klassendiagramm
Objektdiagramm
15
Konstruktor / Destruktor
Zur Erzeugung von Objekten verfügt eine
Klasse über eine spezielle Methode, die
sogenannte Konstruktormethode.
Zur Vernichtung von Objekten verfügt eine
Klasse über eine sogenannte
Destruktormethode.
Konstruktor
Ein Software-Objekt hat - wie viele Objekte der realen Welt - eine bestimmte Lebensdauer. Es
muss erzeugt werden, bevor es in Aktion treten kann, und kann auch wieder vernichtet
werden.
In einem Klassendiagramm wird eine Konstruktormethode dadurch gekennzeichnet, dass sie
denselben Namen wie die Klasse selbst trägt. Oft wird diese spezielle Methode in
Klassendiagrammen aber auch weggelassen. Beachte, dass eine Konstruktormethoden keine
Methode ist, die ein Objekt ausführen kann.
Destruktormethoden werden in der Regel in Klassendiagrammen weggelassen.
16
Klassendeklaration in Python
Klassenname
Schlüsselwort
Oberklasse
Doppelpunkt
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
Attribute
self.stand = 0
Einrückung
Konstruktor
def einzahlen(self, betrag):
self.stand = self.stand + betrag
Methode
def auszahlen(self, betrag):
self.stand = self.stand - betrag
Methode
Referenz auf Objekt
17
Objekterzeugung in Python
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
self.stand = 0
def einzahlen(self, betrag):
self.stand = self.stand + betrag
def auszahlen(self, betrag):
self.stand = self.stand - betrag
>>> k = Konto(5)
Erzeugung eines Objekts
>>> k.stand
0.0
>>> del k
Vernichtung eines Objekts
>>> k.stand
Traceback (most recent call last):
File ...
NameError: name 'k' is not defined
>>>
Klassendeklaration
>>> k1 = Konto(5)
>>> k2 = Konto(8)
>>> k1.nr
5
>>> k1.stand
0
>>> k2.nr
8
>>> k2.stand
0
>>> k1.__dict__
{'nr': 5, 'stand': 0}
>>> k2.__dict__
{'nr': 8, 'stand': 0}
Inspektion eines Objekts
Übungen
18
Aufgabe 1 (siehe www.inf-schule.de 1.12.2.5)
Gegeben ist eine Implementierung der Klasse Wuerfel():
from random import randint
class Wuerfel(object):
def __init__(self):
self.augen = 1
def werfen(self):
self.augen = randint(1, 6)
Erzeuge drei Objekte der Klasse Wuerfel und würfele hiermit solange, bis mindestens einer der
Würfel eine 6 liefert.
19
Übungen
Aufgabe 2 (siehe www.inf-schule.de 1.12.2.5)
Gegeben ist das folgende Klassendiagramm zur Klasse Bruch:
Was soll mit einem Objekt der Klasse Bruch beschrieben werden? Entwickle eine geeignete
Implementierung und teste sie mit einem Python-Dialog.
20
Übungen
Aufgabe 3 (siehe www.inf-schule.de 1.12.2.5)
Wenn man modulo einer vorgegebenen Zahl (man nennt sie
auch Modul) zählt, dann bildet man jeweils den Rest bei der
Division durch die vorgegebene Zahl.
Betrachte als Beispiel die vorgegebene Zahl (Modul) 5. Wenn
man modulo 5 zählt, dann geht das so: 0 modulo 5, 1
modulo 5, 2 modulo 5, 3 modulo 5, 4 modulo 5, 5 modulo 5,
6 modulo 5, ... Berechnet man jeweils die Reste, dann ergibt
das folgende die Zahlenfolge 0, 1, 2, 3, 4, 0, 1, ... .
Wenn man modulo einer vorgegebenen Zahl n zählt, dann
ergibt das also die Zahlenfolge 0, 1, ..., (n-1), 0, 1, ....
Konzipiere eine Klasse ModuloZaehler (mit einem
Klassendiagramm), die Python-Dialoge wie den folgenden
ermöglicht. Implementiere die Klasse und teste sie mit
geeigneten Python-Dialogen.
>>>
>>>
3
>>>
0
>>>
>>>
1
>>>
>>>
2
>>>
>>>
0
>>>
>>>
2
>>>
>>>
0
z = ModuloZaehler(3)
z.modul
z.stand
z.weiterzaehlen()
z.stand
z.weiterzaehlen()
z.stand
z.weiterzaehlen()
z.stand
z.zurueckzaehlen()
z.stand
z.nullsetzen()
z.stand
Übungen
21
Aufgabe 5 (siehe www.inf-schule.de 1.12.2.5)
Die Klasse Schlange kann man verwenden, um Warteschlangen zu simulieren. Erläutere, was
die Methoden der Klasse Schlange bewirken. Verdeutliche deine Erläuterungen jeweils mit
einem geeigneten Python-Protokoll.
class Schlange(object):
def __init__(self):
self.liste = []
def istLeer(self):
if self.liste == []:
return True
else:
return False
def mitLetztem(self, element):
self.liste = self.liste + [element]
...
def ohneErstes(self):
if not self.istLeer():
self.liste = self.liste[1:]
...
def anzahlElemente(self):
return len(self.liste)
def getSchlange(self):
return self.liste
def setSchlange(self, liste):
self.liste = liste
Übungen
22
Aufgabe 6 (siehe www.inf-schule.de 1.12.2.5)
Die folgende Deklaration des Konstruktors
erlaubt es, Objekte flexibel mit
Anfangswerten zu versehen:
class Konto(object):
def __init__(self, nummer=0, betrag=0):
self.nr = nummer
self.stand = betrag
def einzahlen(self, betrag):
self.stand = self.stand + betrag
def auszahlen(self, betrag):
self.stand = self.stand - betrag
Erkläre, wie die jeweiligen Attributwerte der
Objekte zustande kommen.
>>> k1 = Konto()
>>> k1.nr
0
>>> k1.stand
0
>>> k2 = Konto(1)
>>> k2.nr
1
>>> k2.stand
0
>>> k3 = Konto(2, 1000.0)
>>> k3.nr
2
>>> k3.stand
1000.0
>>> k4 = Konto(betrag=400.0)
>>> k4.nr
0
>>> k4.stand
400.0
23
Teil 3
Verwaltung von Objekten
24
Objekte und ihre Identität
>>> k1 = Konto(3)
>>> k1
<__main__.Konto object at 0x0135D670>
>>> id(k1)
20305520
>>> hex(20305520)
'0x135d670'
>>> k2 = Konto(4)
>>> id(k2)
20307184
Python-Dialog
Aufgabe:
Was verbirgt sich wohl hinter der
Identitätsnummer eines Objekts?
Prüfe mit geeigneten Python-Dialogen, ob
sich die Identitätsnummer eines Objekts
ändert, wenn sich der Zustand eines
Objekts beim Ausführen einer Methode
ändert.
Konto kopieren?
25
>>>
>>>
>>>
???
>>>
???
>>>
>>>
???
>>>
???
>>>
>>>
???
>>>
???
>>>
k1 = Konto(6)
k2 = k1
k1.stand
k2.stand
k2.einzahlen(100.0)
k1.stand
k2.stand
k2 = Konto(7)
k1.stand
k2.stand
Python-Dialog
Aufgabe:
Stell Vermutungen auf, was anstelle der
drei Fragezeichen jeweils steht. Teste, ob
deine Vermutungen stimmen. Kannst du
dir die Ergebnisse erklären? Benutze auch
den id-Operator, um Einsicht über die
verwalteten Objekte zu erhalten.
26
Identität von Objekten
(Daten-) Objekte haben - analog zu Objekten unserer Lebenswelt - ebenfalls eine Identität.
Zur eindeutigen Identifizierung werden sie mit Identitätsnummern versehen.
Verschiedene Objekte unterscheiden sich in ihrer Identitätsnummer. Sie können aber durchaus
denselben Objektzustand haben.
Ein Objekt behält während seiner Lebensdauer immer die einmal vergebene
Identitätsnummer. Auch wenn sich der Zustand des Objekts verändert, so bleibt doch die
Identitätsnummer des Objekts bestehen.
Häufig verwendet hierzu man eine Adresse im Speicher des Rechners als Identitätsnummer.
Die Identitätsnummer eines Objekts zeigt dann auf den Speicherbereich, in dem die Daten
des Objekts abgelegt sind. Diese Identifikation von Objekten durch eine Lokalisierung im
Speicher setzt natürlich voraus, dass Objekte im Speicher nicht hin und her wandern, sondern
dass der einmal zugeteilte Speicherbereich während der Lebensdauer eines Objekts bestehen
bleibt. Wir gehen im Folgenden von dieser Vorstellung aus.
27
Zeiger / Referenzen
Eine Variable ist ein Name, der (in der Regel) mit einem Objekt verknüpft ist. Wenn eine
Variable ein (Daten-) Objekt verwaltet, dann verwaltet es die Speicheradresse (bzw.
Identitäsnummer) dieses Objekts. Da die Speicheradresse auf das Objekt zeigt bzw. das
Objekt referenziert, nennt man eine solche Adresse auch Zeiger bzw. Referenz und die
Variable zur Verwaltung der Adresse Zeigervariable bzw. Referenzvariable.
28
Zuweisungen bei Zeigervariablen
k1 = Konto(6)
k2 = k1
k2.einzahlen(100.0)
k2 = Konto(7)
Objekte in Python
29
Veränderbares
Objekt
from konto import *
def null(konto):
print(id(konto))
konto.stand = 0.0
print(id(konto))
k = Konto(9)
k.einzahlen(100.0)
print(k.stand)
print(id(k))
null(k)
print(k.stand)
print(id(k))
Unveränderbares Objekt
def null(zahl):
print(id(zahl))
zahl = 0.0
print(id(zahl))
z = 100.0
print(z)
print(id(z))
null(z)
print(z)
print(id(z))
kein Seiteneffekt
Seiteneffekt
Python unterscheidet zwischen veränderbaren und unveränderbaren Objekten.
Übungen
30
Aufgabe 1 (siehe www.inf-schule.de 1.12.3.5)
Wenn man den Objektbezeichner vom Python-Interpreter auswerten lässt, dann wird der vom
Bezeichner verwaltete Wert angezeigt. Warum zeigt der Python-Dialog, dass hier Zeiger
verwaltet werden?
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
self.stand = 0
def einzahlen(self, betrag):
self.stand = self.stand + betrag
def auszahlen(self, betrag):
self.stand = self.stand - betrag
>>> k1 = Konto(6)
>>> k2 = k1
>>> k1
<__main__.Konto object at 0x01DA7F10>
>>> k2
<__main__.Konto object at 0x01DA7F10>
>>> k2 = Konto(8)
>>> k2
<__main__.Konto object at 0x01DB5CB0>
Übungen
31
Aufgabe 2 (siehe www.inf-schule.de 1.12.3.5)
Jedes Objekt wird zur Identifierung mit einer eindeutigen Identitätsnummer versehen. Mit Hilfe
des id-Operators lässt sich diese Identitätsnummer in Python ermitteln. Was zeigt der
abgebildete Python-Dialog?
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
self.stand = 0
def einzahlen(self, betrag):
self.stand = self.stand + betrag
def auszahlen(self, betrag):
self.stand = self.stand - betrag
>>>
>>>
>>>
>>>
>>>
>>>
k1 = Konto(6)
k2 = k1
id(k1) 31153488
id(k2) 31153488
k2 = Konto(8)
id(k2) 31096624
32
Übungen
Aufgabe 3 (siehe www.inf-schule.de 1.12.3.5)
Die Funktion mitNeuemErsten soll dazu dienen, in einer Liste das erste Element
auszutauschen. Vegleiche die beiden folgenden Implementierungen und erkläre das
unterschiedliche Verhalten.
def mitNeuemErsten(liste, element):
liste[0] = element
return liste
def mitNeuemErsten(liste, element):
hilf = [element] + liste[1:]
return hilf
L = [1, 2, 3]
M = mitNeuemErsten(L, 0)
print(L)
print(M)
L = [1, 2, 3]
M = mitNeuemErsten(L, 0)
print(L)
print(M)
33
Teil 4
Modularisierung und Datenkapselung
34
Konto überziehen
Ein Konto soll höchstens um 1000 Euro überzogen werden dürfen.
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
self.stand = 0
self.minimum = -1000.0
def einzahlen(self, betrag):
self.stand = self.stand + betrag
def auszahlen(self, betrag):
if self.stand - betrag >= self.minimum:
self.stand = self.stand - betrag
else:
print("Auszahlung nicht möglich!")
>>> k = Konto(9)
>>> k.stand = 600.0
>>> k.stand
600.0
>>> auszahlungsbetrag = 2750.0
>>> k.stand = k.stand - auszahlungsbetrag
>>> k.stand
-2150.0
Nutzung der Klasse
Implementierung der Klasse
Aufgabe 1:
Warum ist dieser Dialog nicht im Sinne des Bankkontenverwaltungssystems?
35
Konto überziehen
Die Entwickler der Klasse Konto veröffentlichen folgende Schnittstelle dieser Klasse:
from konto import Konto
k = Konto(9)
# Testlauf
k.einzahlen(600.0)
print(k.getStand())
auszahlungsbetrag = 2750.0
k.auszahlen(auszahlungsbetrag)
print(k.getStand())
Schnittstelle zur Klasse
Nutzung der Klasse
Aufgabe 2:
Warum macht es hier Sinn, die Attribute der Klasse Konto nicht zu veröffentlichen und eine
Veränderung von Attributwerten nur über veröffentlichte Merhoden zu erlauben?
Aufgabe 3:
Im Testprogramm wird die Methode getStand benutzt, die in der Schnittstelle vorgesehen ist.
Was soll diese Methode leisten? Ergänze die oben gezeigte Implementierung der Klasse Konto
um die noch fehlenden Methoden und führe das Testprogramm aus.
36
Modularisierung
Modularisierung ist ein Prinzip, nach dem viele Systeme entwickelt werden. Die Idee besteht
darin, das Gesamtsystem nach dem Baukastenprinzip aus Einzelbausteinen (den sogenannten
Modulen) zusammenzusetzen.
"Unsere Partyzelte können in verschiedenen
Größen aufgebaut werden. Da die Partyzelte
und Festzelte aus Modulen bestehen, ist es
sehr einfach, sie zu erweitern. Die Abbildung
zeigt ein mögliches Kombinationsbeispiel der
Module."
Ein Softwaremodul ist eine in sich abgeschlossene Einheit, die man vielfältig bei Problemlösungen einsetzen kann. Es reicht dabei zu wissen, welche Operationen die Einheit dem
Benutzer zur Verfügung stellt. Wie die Operationen programmiert sind, muss man dagegen
nicht wissen.
Grundidee der objektorientierten
Modularisierung ist es, Softwaremodule als
Klassen zu konzipieren .
37
Modularisierung in Python
from konto import Konto
k = Konto(9)
# Testlauf
k.einzahlen(600.0)
print(k.getStand())
auszahlungsbetrag = 2750.0
k.auszahlen(auszahlungsbetrag)
print(k.getStand())
import konto
k = konto.Konto(9)
# Testlauf
k.einzahlen(600.0)
print(k.getStand())
auszahlungsbetrag = 2750.0
k.auszahlen(auszahlungsbetrag)
print(k.getStand())
Der Name "Konto" wird in den aktuellen
Namensraum übernommen.
from konto import *
k = Konto(9)
# Testlauf
k.einzahlen(600.0)
print(k.getStand())
auszahlungsbetrag = 2750.0
k.auszahlen(auszahlungsbetrag)
print(k.getStand())
38
Geheimnisprinzip / Datenkapselung
Beim Autobau wird somit - zumindest in bestimmten Bereichen - das Geheimnisprinzip
angewandt. Bestimmte Eigenschaften des Motors können nur über speziell hierfür
vorgesehene Schnittstellen ermittelt werden. So kann der aktuelle Ölstand nur an einem
hierfür vorgesehenen Messstab abgelesen werden. Änderungen am aktuellen Motorzustand
können direkt ebenfalls nur an bestimmten hierfür vorgesehenen Stellen vorgenommen
werden. Motoröl lässt sich nur in die hierfür vorgesehene Öffnung einfüllen. Alles weitere über
das Innere des Motors bleibt für den normalen Autofahrer unzugänglich und in diesem Sinne
geheim.
Bei der objektorientierten Software-Entwicklung geht man völlig analog vor. Nach dem
Geheimnisprinzip werden die internen Daten eines Objekts (die in der Regel über Attribute
verwaltet werden) so verborgen, dass ein direkter Zugriff hierauf nicht möglich ist. Jeder
Zugriff auf interne Daten und jede Veränderung von internen Daten darf nur über spezielle,
hierfür vorgesehene Methoden erfolgen. Man nennt diese Vorgehensweise auch
Datenkapselung.
39
Zugriffsrechte / Zugriffsmethoden
Um interne Daten kapseln zu können, werden Zugriffrechte festgelegt. Der Entwickler einer
Klasse hat die Möglichkeit, Attribute und Methoden einer Klasse als öffentlich oder privat zu
deklarieren. Lesende und schreibende Zugriffe auf Attribute bzw. Methoden eines Objekts sind
nur möglich, wenn diese öffentlich sind. Private Attribute bzw. Methoden können dagegen nur
bei der Implementierung der betreffenden Klasse benutzt werden.
Im Klassendiagramm werden die Zugriffsrechte auf die
Attribute und Methoden mit Hilfe der Symbole + (für
öffentlich) und - (für privat) festgelegt.
Verfolgt man die Strategie, alle Attribute als privat zu
deklarieren, so besteht keine Möglichkeit, direkt
schreibend oder lesend auf Attributwerte zuzugreifen. Um
dennoch solche Zugriffe zu erlauben, werden spezielle
öffentliche Zugriffsmethoden bereitgestellt. Das
Klassendiagramm wird daher um solche Zugriffsmethoden
erweitert.
40
Zugriffsrechte in Python
class Konto(object):
def __init__(self, nummer):
self.__nr = nummer
self.__stand = 0
self.__minimum = -1000.0
Ein Attribut / eine Methode wird in
Python zu einem privaten Attribut,
wenn der Attributname mit zwei
Unterstrichen beginnt und nicht mit
Unterstrichen endet. Beginnt der
Attributname / Methodenname
nicht mit einem Unterstrich, so ist
das Attribut öffentlich.
def einzahlen(self, betrag):
self.__stand = self.__stand + betrag
def auszahlen(self, betrag):
if self.__stand - betrag >= self.__minimum:
self.__stand = self.__stand - betrag
else:
print("Auszahlung nicht möglich!")
def getStand(self):
return self.__stand
def setStand(self, stand):
if stand >= self.__minimum:
self.__stand = stand
else:
print("Initialisierung nicht möglich!")
# ...
41
Datenkapselung in Python
>>> k = Konto(3)
>>> k.__stand
Traceback (most recent call last):
File ...
AttributeError: 'Konto' object has no attribute '__stand'
>>> k.__dict__
{'_Konto__minimum': -1000.0, '_Konto__nr': 3, '_Konto__stand': 0}
>>> k._Konto__stand
0
Wie erwartet kann man auf das private Attribut __stand des neu erzeugten Objekts k nicht
zugreifen. Python meldet als Fehler, dass es kein Attribut __stand gibt. Der Aufruf k.__dict__
verrät, woran das liegt. Ein Aufruf wie k.__dict__ listet sämtliche Attribute mit den zugehörigen
Attributwerten des betreffenden Objekts auf. Interessant ist hier, dass sich das private Attribut
__stand hinter einem anderen Namen versteckt. Wenn man weiß, wie der neue Name - hier
_Konto__stand - gebildet wird, dann kann man durchaus auf das betreffende Attribut
zugreifen. Also: Private Attribute werden in Python mit anderen Namen versehen, so dass kein
direkter Zugriff möglich ist. Kennt man den Namen, hinter dem sich ein privates Attribut
verbirgt, so kann man durchaus auf dieses Attribut zugreifen. Python liefert also keinen echten
Zugriffsschutz.
42
Datenkapselung in Python
>>> k = Konto(3)
>>> k.__stand
Traceback (most recent call last):
File ...
AttributeError: 'Konto' object has no attribute '__stand'
>>> k.__dict__
{_Konto__minimum': -1000.0, '_Konto__nr': 3, '_Konto__stand': 0}
>>> k.__stand = 100.0
>>> k.__stand
100.0
>>> k.__dict__
{_Konto__minimum': -1000.0, '_Konto__nr': 3, '_Konto__stand': 0, '__stand': 100.0}
Ein erster Zugriff auf das private Attribut __stand scheitert. Dann aber ist es - entgegen aller
Zugriffslogik - scheinbar möglich, dem privaten Attribut __stand einen Wert zuzuweisen. Der
Aufruf k.__dict__ erklärt erst, was hier passiert ist. Neben dem privaten Attribut __stand, das
sich hinter dem neuen Namen _Konto__stand versteckt, gibt es noch öffentliches Attribut
__stand, auf das man direkt zugreifen kann.
Wir werden im Folgenden bei der Implementierung von Klassen in Python keine Attribute als
private Attribute deklarieren. In der Regel werden wir auch keine Zugriffsmethoden einführen
und nutzen. Nur in begründeten Ausnahmefällen werden wir von dieser Vereinbarung
abweichen.
43
Schnittstellen
Die Schnittstelle einer Klasse liefert alle Informationen, die man benötigt, um die Klasse
benutzen zu können. Hierzu gehört eine genaue Beschreibung aller öffentlichen Attribute und
Methoden der Klasse. Für jedes Attribut benötigt man den erwarteten Datentyp, für jede
Methode die Signatur (d. h. die genaue Festlegung der Parametertypen und bei Funktionen
des Rückgabetyps) und eine Verhaltensbeschreibung.
Konto(nummer: int)
nachher: Ein Objekt der Klasse Konto ist erzeugt. Der Wert des
Attributs nr entspricht dem übergebenen Wert des Parameters
nummer, der Wert des Attributs stand beträgt 0, der Wert des
Attributs minimum beträgt -1000.0.
auszahlen(betrag: float)
vorher: Das Konto-Objekt hat einen beliebigen Zustand.
nachher: Der Wert des Attributs stand des Konto-Objekts ist um
den übergebenen Wert des Parameters betrag reduziert.
44
Übungen
Aufgabe 1 (siehe www.inf-schule.de 1.12.4.8)
Zur Klasse Wuerfel soll folgende Implementierung in einer
Datei wuerfel.py abgespeichert sein:
from random import randint
class Wuerfel(object):
def __init__(self):
self.augen = 1
def werfen(self):
self.augen = randint(1, 6)
(a) Was leistet das folgende Programm, das das Modul
Wuerfel als Baustein benutzt?
(b) Es soll getestet werden, wie oft man drei Würfel
werfen muss, bis mindestens einer eine 6 liefert.
Entwickle ein geeignetes Simulationsprogramm, das die
Klasse Wuerfel als Baustein benutzt.
from wuerfel import *
# Würfelprogramm
w = Wuerfel()
w.werfen()
versuche = 1
while w.augen != 6:
w.werfen()
versuche = versuche + 1
print("Versuche:", versuche)
45
Übungen
Aufgabe 2 (siehe www.inf-schule.de 1.12.4.8)
Folgende Klassen sollen als Bausteine zur Simulation des
Spiels "chuck a luck" zur Verfügung gestellt werden:
(a) Implementiere diese Klassen. Mit Hilfe dieser
Bausteine sollen dann Python-Dialoge wie der folgende
möglich sein.
(b) Mit Hilfe eines Simulationsprogramms soll ermittelt
werden, ob das chuck-a-luck-Spiel fair ist.
>>>
>>>
>>>
>>>
>>>
>>>
>>>
99
>>>
>>>
3
>>>
>>>
>>>
>>>
3
>>>
6
>>>
2
>>>
>>>
101
k = Konto(100)
s = Spielzahl()
wA = Wuerfel()
wB = Wuerfel()
wC = Wuerfel()
k.abheben(1)
k.stand
s.setzen(3)
s.zahl
wA.werfen()
wB.werfen()
wC.werfen()
wA.augen
wB.augen
wC.augen
k.einzahlen(2)
k.stand
Übungen
46
Aufgabe 3 (siehe www.inf-schule.de 1.12.4.8)
(a) Erstell ein Klassendiagramm und eine
Schnittstellenbeschreibung zur Klasse Bruch.
(b) Entwickle ein Testprogramm, das die
Klasse Bruch als Modul benutzt.
class Bruch(object):
def __init__(self, z, n):
self.zaehler = z
self.nenner = n
def erweitern(self, k):
self.zaehler = self.zaehler * k
self.nenner = self.nenner * k
...
def kuerzen(self, k):
if (self.zaehler % k == 0) and \
(self.nenner % k == 0):
self.zaehler = self.zaehler // k
self.nenner = self.nenner // k
...
def vollstaendigKuerzen(self):
# ggT von Zähler und Nenner best.
x = self.zaehler
y = self.nenner
while y > 0:
h=x%y
x=y
y=h
ggt = x
# kürzen
self.kuerzen(ggt)
(c) Füge der
def add(self, b):
Klasse Bruch
x1 = self.zaehler
weitere
x2 = self.nenner
Operationen
y1 = b.zaehler
hinzu und teste
y2 = b.nenner
z1 = x1*y2 + x2*y1 diese
Erweiterung.
z2 = x2*y2
self.zaehler = z1
self.nenner = z2
self.vollstaendigKuerzen()
47
Übungen
Aufgabe 5 (siehe www.inf-schule.de 1.12.4.8)
Teste die Einbindung folgender Modulimporte und ihre Auswirkung auf den globalen
Namensraum.
Warum wird bei sehr umfangreichen Modulen empfohlen, die erste oder dritte der oben
aufgelisteten Einbindungsvarianten zu benutzen?
>>> from random import randint
>>> globals()
>>> from random import *
>>> globals()
>>> import random
>>> globals()
Übungen
48
Aufgabe 6 (siehe www.inf-schule.de 1.12.4.8)
(a) Teste diese Implementierung der Klasse Bruch. Irgend etwas stimmt hier nicht. Findest du
den Fehler? Benutze die Operation __dict__() zur Fehlersuche. Erkläre, was hier schiefläuft.
(b) Warum ist es so schwierig, Flüchtigkeitsfehler wie den oben gezeigten zu finden?
class Bruch(object):
def __init__(self, z, n):
self.zaehler = z
self.nenner = n
def erweitern(self, k):
self.zahler = self.zaehler * k
self.nenner = self.nenner * k
def kuerzen(self, k):
if (self.zaehler % k == 0) and \
(self.nenner % k == 0):
self.zaehler = self.zaehler // k
self.nenner = self.nenner // k
49
Teil 5
Beziehungen
Verwaltung des Kontoinhabers
50
S
Konto-Nr.5
Adriana Müller
Kontoauszug
Blatt 3
Datum
Erläuterung
01.07.2009
Handykosten
08.07.2009
Zuschuss von Oma und Opa
10.07.2009
Schuhe
Kontostand in EUR, 11.07.2009
Vorschlag 1:
Betrag
45.00 -
Der Kontoinhaber soll jetzt
ebenfalls mitverwaltet
werden. Hierzu muss das
Objektmodell erweitert
werden. Mehrere Vorschläge
stehen zur Diskussion
100.00 +
80.00 -
50.00 +
Aufgabe:
Vergleiche die folgenden
Vorschläge.
Vorschlag 2:
51
Verwaltung des Kontoinhabers
Vorschlag 2:
Vorschlag 3:
Aufgabe:
Welche Nachteile zeigen
sich bei Vorschlag 2, wenn
es mehrere Konten und
mehrere Kunden gibt?
Vergleiche Vorschlag 2 mit
Vorschlag 3.
52
Verwaltung des Kontoinhabers
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
self.stand = 0.0
self.inhaber = None
def einzahlen(self, betrag):
self.stand = self.stand + betrag
def auszahlen(self, betrag):
self.stand = self.stand - betrag
class Kunde(object):
def __init__(self, name, vorname):
self.name = name
self.vorname = vorname
from konto_kunde import *
# Erzeugung der Objekte
konto1 = Konto(5)
konto2 = Konto(11)
konto2.stand = 200.0
kunde1 = Kunde("Müller", "Adriana")
kunde2 = Kunde("Meier", "Anatol")
konto1.inhaber = kunde2
konto2.inhaber = kunde1
# Ausgaben
print("Kontonummer: ", konto1.nr)
print("Inhaber(in): ", konto1.inhaber.vorname, \
konto1.inhaber.name)
print("Kontostand: ", konto1.stand)
print()
print("Kontonummer: ", konto2.nr)
print("Inhaber(in): ", konto2.inhaber.vorname, \
konto2.inhaber.name)
print("Kontostand: ", konto2.stand)
Aufgabe:
Erkläre, wie die Objektkonstellation aus Vorschlag 3 hier realisiert wird. Stell auch eine
Vermutung auf, was das Testprogramm auf dem Bildschirm ausgibt.
53
Beziehung
Wenn ein Objekt über einen Zeiger (eine Referenz) Zugriff auf ein anderes Objekt hat, so liegt
eine (gerichtete) Beziehung zwischen den Objekten vor.
Mit Hilfe eines Aufrufs wie
z.B. konto1.inhaber kann
das Konto-Objekt konto1
auf Daten des
zugeordneten KundeObjekts zugreifen, z.B.
mit konto1.inhaber.name
auf das entsprechende
Attribut. Das KontoObjekt konto1 hat somit
Zugriff auf ein KundeObjekt, z.B. kunde2. Man
sagt auch, dass das
Konto-Objekt konto1 in
Beziehung zum KundeObjekt kunde2 steht.
Objektdiagramm
Klassendiagramm
54
Beziehungsmuster
Muster:
Objekt der Klasse A kennt
Objekt der Klasse B
Muster:
Objekt der Klasse A erzeugt
Objekt der Klasse B
Muster:
Objekt der Klasse A kennt
Objekt der Klasse B und
umgekehrt
Muster:
Objekt der Klasse A kennt
mehrere Objekte der Klasse B
55
Implementierung von Beziehungen
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
self.stand = 0.0
self.inhaber = None
def einzahlen(self, betrag):
self.stand = self.stand + betrag
def auszahlen(self, betrag):
self.stand = self.stand - betrag
class Kunde(object):
def __init__(self, name, vorname):
self.name = name
self.vorname = vorname
Muster:
Objekt der Klasse A kennt
Objekt der Klasse B
from bank0 import *
# Erzeugung der Objekte
konto1 = Konto(5)
konto2 = Konto(11)
konto2.stand = 200.0
kunde1 = Kunde("Müller", "Adriana")
kunde2 = Kunde("Meier", "Anatol")
konto1.inhaber = kunde2
konto2.inhaber = kunde1
56
Implementierung von Beziehungen
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
self.stand = 0.0
self.inhaber = None
def einzahlen(self, betrag):
self.stand = self.stand + betrag
def auszahlen(self, betrag):
self.stand = self.stand - betrag
class Kunde(object):
def __init__(self, name, vorname):
self.name = name
self.vorname = vorname
self.konto = None
Muster:
Objekt der Klasse A kennt Objekt der
Klasse B und umgekehrt
from bank1 import *
# Erzeugung der Objekte
konto1 = Konto(5)
konto2 = Konto(11)
konto2.stand = 200.0
kunde1 = Kunde("Müller", "Adriana")
kunde2 = Kunde("Meier", "Anatol")
konto1.inhaber = kunde2
konto2.inhaber = kunde1
kunde1.konto = konto2
kunde2.konto = konto1
57
Implementierung von Beziehungen
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
self.stand = 0.0
self.inhaber = None
def einzahlen(self, betrag):
self.stand = self.stand + betrag
def auszahlen(self, betrag):
self.stand = self.stand - betrag
class Kunde(object):
def __init__(self, name, vorname):
self.name = name
self.vorname = vorname
self.konten = []
Liste
def kontoHinzufuegen(self, konto):
self.konten = self.konten + [konto]
from bank2 import *
# Erzeugung der Objekte
konto1 = Konto(5)
konto2 = Konto(11)
konto2.stand = 200.0
konto3 = Konto(19)
konto3.stand = 150.0
konto4 = Konto(21)
konto4.stand = -50.0
kunde1 = Kunde("Müller", "Adriana")
kunde2 = Kunde("Meier", "Anatol")
konto1.inhaber = kunde2
konto2.inhaber = kunde1
konto3.inhaber = kunde1
konto4.inhaber = kunde1
kunde1.kontoHinzufuegen(konto2)
kunde1.kontoHinzufuegen(konto3)
kunde1.kontoHinzufuegen(konto4)
kunde2.kontoHinzufuegen(konto1)
Muster:
Objekt der Klasse A kennt mehrere Objekte der
Klasse B
58
Implementierung von Beziehungen
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
self.stand = 0.0
self.inhaber = None
def einzahlen(self, betrag):
self.stand = self.stand + betrag
from bank3 import *
from random import *
# Erzeugung der Objekte
bank = Bank()
for i in range(8):
bank.erzeugeKonto()
for konto in bank.konten:
konto.einzahlen(float(randint(0, 100)))
def auszahlen(self, betrag):
self.stand = self.stand - betrag
class Bank(object):
def __init__(self):
self.konten = []
self.naechsteKontoNr = 0
def erzeugeKonto(self):
konto = Konto(self.maxKontoNr)
self.konten = self.konten + [konto]
self.naechsteKontoNr = self.naechsteKontoNr + 1
Muster:
Objekt der
Klasse A
erzeugt
Objekte der
Klasse B
59
Operationen als Dienste
Objekte können (in aller Regel) bestimmte Operationen mit den von ihnen verwalteten Daten
ausführen. Die Ausführung einer Operationen wird als Dienst anderen Objekten zur Verfügung
gestellt. Andere Objekte können den zur Verfügung gestellten Dienst dann nutzen. Hier wird
also die Anbieter-Nutzer-Sichtweise benutzt.
Ein Bank-Objekt bietet z.B. den Dienst ueberweisen an.
Ein Konto-Objekt bietet z.B. den Dienst einzahlen an.
60
Interaktion zwischen Objekten
Die Analogien zur Lebenswelt ermöglichen es,
die Ausführung objektorientierter Programme
in einem Rollenspiel zu verdeutlichen, bei
dem Personen die Rolle von Objekten
übernehmen.
Wenn das Bank-Objekt den Dienst "ueberweisen" ausführt, dann schickt es zunächst eine
Nachricht auszahlen(...) an das betreffende Konto-Objekt und anschließend eine Nachricht
einzahlen(...) an das andere betreffende Konto-Objekt. Das Bank-Objekt interagiert also hier
mit zwei Konto-Objekten. Dies ist deshalb möglich, weil das Bank-Objekt gemäß
Klassendiagramm oben in Beziehung zu den Konto-Objekten steht.
61
Interaktion zwischen Objekten
Wenn ein Objekt den Dienst eines anderen Objekt nutzen will, dann schickt es ihm eine
Nachricht. Das Senden einer Nachricht bedeutet, ein Objekt zu veranlassen, eine seiner als
Dienste zur Verfügung gestellten Operationen. Das Versenden von Nachrichten wird als
Interaktion zwischen Objekten gedeutet. Voraussetzung für eine Interaktion zwischen
Objekten ist, dass diese miteinander in Beziehung stehen.
Sequenzdiagramm
Wenn das Bank-Objekt den Dienst "ueberweisen" ausführt, dann schickt es zunächst eine
Nachricht auszahlen(...) an das betreffende Konto-Objekt und anschließend eine Nachricht
einzahlen(...) an das andere betreffende Konto-Objekt. Das Bank-Objekt interagiert also hier
mit zwei Konto-Objekten. Dies ist deshalb möglich, weil das Bank-Objekt gemäß
Klassendiagramm oben in Beziehung zu den Konto-Objekten steht.
Übungen
62
Aufgabe 1 (siehe www.inf-schule.de 1.12.5.6)
Erzeuge Objekte, die folgende Situation modellieren: Kunde Werner Schmidt hat das Konto mit
der Nummer 23. Kundin Theresa Meier hat das Konto mit der Nummer 42. Kundin Alexandra
Roth hat das Konto mit der Nummer 15.
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
self.stand = 0.0
self.inhaber = None
def einzahlen(self, betrag):
self.stand = self.stand + betrag
def auszahlen(self, betrag):
self.stand = self.stand - betrag
class Kunde(object):
def __init__(self, name, vorname):
self.name = name
self.vorname = vorname
63
Übungen
Aufgabe 2 (siehe www.inf-schule.de 1.12.5.6)
Ein Kunde soll neben einem Erstkonto auch ein Zweitkonto haben können.
(a) Beschreibe eine typische Situation in dieser Bankwelt mit einem Objektdiagramm.
(b) Beschreibe die Bankwelt auch mit einem Klassendiagramm.
(c) Entwickle eine Implementierung zu dieser Bankwelt und ein Testprogramm passend zu
Aufgabe (a).
64
Übungen
Aufgabe 3 (siehe www.inf-schule.de 1.12.5.6)
In der freien Enzyklopädie Wikipedia werden Artikel zu Stichwörtern von Benutzern verfasst.
Eine erste Modellierung der Klassen Artikel und Benutzer könnte wie folgt aussehen:
(a) Implementiere die Klassen und erzeuge Objekte zur Beschreibung folgender Situation:
* Der Artikel zum Stichwort HTML wurde vom Benutzer helmut03 verfasst.
* Der Artikel zum Stichwort CSS wurde vom Benutzer loreley verfasst.
* Der Artikel zum Stichwort Barrierefreiheit wurde vom Benutzer loreley verfasst.
65
Übungen
Aufgabe 3 (siehe www.inf-schule.de 1.12.5.6)
Das Modell soll so erweitert werden, dass Artikel von Benutzern überarbeitet werden können:
(b) Implementiere das erweiterte Modell und erzeuge eine typische Objektsituation.
Verdeutliche die erzeugte Objektsituation auch mit einem Objektdiagramm.
(c) Wie müsste man die Klasse Benutzer erweitern, wenn hier auch die Mitarbeit an Artikeln
mit einem Referenzattribut erfasst werden soll.
66
Übungen
Aufgabe 4 (siehe www.inf-schule.de 1.12.5.6)
Ein Geometrieprogramm soll verschiedene geometrische Objekte verwalten. Kannst du
passende Klassen konzipieren und implementieren, so dass folgendes Testprogramm sinnvoll
ausgeführt werden kann.
from geometrie import *
# Punkte
p1 = Punkt(0, 0)
p2 = Punkt(0, 10)
p3 = Punkt(10, 10)
p4 = Punkt(10, 0)
p5 = Punkt(5, 15)
# Rechtecke und Dreieck (als n-Eck)
rechteck = Rechteck(p1, p3)
dreieck = Neck([p2, p3, p5])
# Haus des Nikolaus als Figur
haus_nikolaus = Figur()
haus_nikolaus.hinzufuegen(rechteck)
haus_nikolaus.hinzufuegen(dreieck)
# Punkt verschieben und ausgeben
p1.verschieben(4, 1)
...
67
Teil 6
Miniwelt und Datenmodell
Bankwelt im Computer
68
S
Konto-Nr.5
Adriana Müller
Kontoauszug
Blatt 3
Datum
Erläuterung
01.07.2009
Handykosten
08.07.2009
Zuschuss von Oma und Opa
10.07.2009
Schuhe
Kontostand in EUR, 11.07.2009
Die Bankwelt mit
bestimmten Gegenständen
(Kunden, Konten, ...) und
Vorgängen (Ein-,
Auszahlungen, ...) soll in
einem Programm geeignet
erfasst werden.
Betrag
45.00 100.00 +
80.00 -
50.00 +
Bankwelt im Computer
69
S
Konto-Nr.5
Adriana Müller
Kontoauszug
Blatt 3
Datum
Erläuterung
01.07.2009
Handykosten
08.07.2009
Zuschuss von Oma und Opa
10.07.2009
Schuhe
Kontostand in EUR, 11.07.2009
Aufgabe:
Welche Objekte sind für
welche Aufgaben zuständig?
Welche Vereinfachungen sind
bei dieser Beschreibung
einer Bankwelt
vorgenommen?
Betrag
45.00 100.00 +
80.00 -
50.00 +
70
Bankwelt im Computer
from bank import *
bank = Bank()
# Konten eröffnen
bank.kontoEroeffnen("Müller", "Adriana", 2101)
bank.kontoEroeffnen("Meier", "Adrian", 1507)
bank.kontoEroeffnen("Schuster", "Christiane", 1313)
bank.kontoEroeffnen("Weber", "Alexander", 2276)
# Ausgabe der konten
for kunde in bank.kunden:
print("Kunde:")
print("Name:", kunde.name)
print("Vorname:", kunde.vorname)
print("Kontonummer:", kunde.konto.nr)
print("Kontostand:", kunde.konto.stand)
print()
# Transaktion
print("Einzahlung")
pin = int(input("PIN:"))
if bank.existiertPIN(pin):
meineKontoNr = bank.getKontoNr(pin)
betrag = float(input("Betrag:"))
bank.einzahlen(meineKontoNr, betrag) ...
Aufgabe:
Lade dir die Datei bank.py mit einer
Implementierung der Klassen
herunter. Versuche, mit den
Objekten Vorgänge der Bankwelt
durchzuspielen. Das folgende
Python-Testprogramm zeigt, wie das
gehen könnte.
Miniwelt
71
Mit Miniwelt bezeichnen wir den Weltausschnitt / Gegenstandsbereich, der dem zu
entwickelnden Programm (Software-System) zu Grunde liegt.
S
Konto-Nr.5
Adriana Müller
Kontoauszug
Blatt 3
Datum
Erläuterung
01.07.2009
Handykosten
08.07.2009
Zuschuss von Oma und Opa
10.07.2009
Schuhe
Kontostand in EUR, 11.07.2009
Betrag
45.00 100.00 +
80.00 -
50.00 +
72
Datenmodell
Ein Modell ist eine vereinfachende
Darstellung einer Miniwelt, die (für
einen bestimmten Zweck
ausgewählte) Teilaspekte der
Miniwelt strukturgetreu beschreibt.
Aufgabe eines objektorientiertes
Datenmodells ist es, die Struktur
der Miniwelt mit Hilfe von Objekten
und deren Beziehungen zu
beschreiben.
73
Zuständigkeiten
Bei der Entwicklung komplexer Software-Systeme ist es günstig, dieses System aus mehreren
Objekten zusammenzusetzen. Jedes Objekt sollte dabei für einen bestimmten
Aufgabenbereich zuständig sein. Ein solches System aus Objekten mit klar umgrenzten
Zuständigkeiten erhöht die Durchschaubarkeit des gesamten Software-Systems und erleichtert
es, das System nachträglich abzuändern oder zu erweitern.
Objekt der Klasse Kunde:
verwaltet die Kundendaten
Objekt der Klasse Konto:
verwaltet die Kontodaten; führt Einund Auszahlungen aus
Objekt der Klasse Bank:
erzeugt und verwaltet alle KundeObjekte und Konto-Objekte;
veranlasst alle Geldtransfers
zwischen Konten; ...
74
UML
UML steht für uniform modeling language und ist eine normierte Bildsprache, mit der man
objektorientierte Modelle beschreiben kann.
Objektdiagramm
Klassendiagramm
Sequenzdiagramm
75
UML-Editor
Violet ist ein sehr einfaches, frei nutzbares Werkzeug zur Erstellung von UML-Diagrammen.
siehe: http://www.horstmann.com/violet/
76
Übungen
Aufgabe 1 (siehe www.inf-schule.de 1.12.6.6)
Beim chuck-a-luck-Spiel soll ein Objekt der Klasse Spiel alle beteiligten Objekte verwalten und
die Spielaktionen als Operationen zur Verfügung stellen.
(a) Skizziere ein Objektdiagramm zur Miniwelt chuck-a-luck.
(b) Woran erkennt man im Klassendiagramm, dass das SpielObjekt für die Erzeugung der weiteren Objekte zuständig ist?
Welche weiteren Zuständigkeiten hat das Spiel-Objekt?
(c) Implementiere dieses Modell. Teste es wie folgt.
from chuckaluck import *
# Erzeugung der Objekte
spiel = Spiel()
# Durchführung eines Spiels
spiel.einsatzZahlen()
spiel.spielzahlSetzen(5)
spiel.wuerfelWerfen()
spiel.gewinnAuszahlen()
# Ausgabe der Spiel
print("Würfel A:", spiel.wuerfelA.augen)
...
77
Übungen
Aufgabe 2 (siehe www.inf-schule.de 1.12.6.6)
Das folgende Klassendiagramm zeigt ein System, mit dem man die Entwicklung einer
Population simulieren kann.
(a) Implementiere die Klasse Population so, dass die Mäusepopulation aus ... (siehe Einstieg Mäusepopulation) als Miniwelt erfasst wird.
(b) Implementiere die Klasse Simulator so, dass sie die Entwicklung der verwalteten
Population beschreibt.
(c) Erstell ein geeignetes Testprogramm, um die Implementierung zu überprüfen..
(d) Was müsste am Datenmodell verändert werden, wenn man die Population aus ... (siehe
Miniprojekt) modellieren wollte?
78
Übungen
Aufgabe 3 (siehe www.inf-schule.de 1.12.6.6)
Ein Zahlenschloss bestehe aus drei Einstellrädern, mit denen die Ziffern der Schlüsselzahl
einzeln eingestellt werden können. Hat man die Schlüsselzahl richtig getroffen, dann ist das
Schloss offen.
Entwickle ein objektorientiertes Datenmodell, das die vorliegende Miniwelt möglichst
strukturgetreu beschreibt. Stell das Datenmodell auch mit Hilfe von UML-Diagrammen dar.
Implementiere und teste das Datenmodell.
79
Teil 7
Datenmodell und
grafische Benutzeroberfläche
80
Eine GUI zur Bankwelt
Das bisher entwickelte Programm zur Verwaltung von Bankkonten soll um eine grafische
Benutzeroberfläche erweitert werden. Der Benutzer soll die Möglichkeit haben, wie an einem
Terminal in der Bank seine Bankgeschäfte zu erledigen. Am Terminal kann man sich den
aktuellen Kontostand anzeigen lassen, Geldbeträge ein- und auszahlen und auch
Überweisungen vorzunehmen.
81
Eine GUI zur Bankwelt
#----------------------------------------------------------# Datenmodell
#----------------------------------------------------------from bank import *
bank = Bank()
bank.initBank()
#----------------------------------------------------------# GUI
#-----------------------------------------------------------
from tkinter import *
# ... Prozeduren zur Ereignisverarbeitung
# Erzeugung des Fensters
fenster = Tk()
fenster.title("Bank")
fenster.geometry('230x330')
...
Aufgabe:
Das gezeigte Programm (siehe
www.inf-schule.de ...) enthält zwar
noch Implementierungslücken, ist
aber nichtsdestotrotz lauffähig.
Teste zunächst das Programm.
Mache dich auch mit dem Quelltext
vertaut. Analysiere insbesondere die
schon implementierten
Ereignisverarbeitungsprozeduren.
Implementiere die noch fehlenden
Implementierungen.
82
from tkinter import *
Eine GUI zur Bankwelt
Aufgabe:
Der folgende Quelltextauszug zeigt
eine andere Implementierung der
grafischen Benutzeroberfläche. Hier
wird ein zusätzliches Objekt
benutzt, um sämtliche GUI-Objekte
zu verwalten. Analysiere das
Programm.
class GUIBank(object):
def __init__(self, bank):
# Referenzattribute zum Datenmodell
self.bank = bank
# Erzeugung des Fensters
self.fenster = Tk()
self.fenster.title("Bank")
self.fenster.geometry('230x330')
# Rahmen PIN
self.rahmenPIN = Frame(master=self.fenster, background="#FFCFC9")
self.rahmenPIN.place(x=5, y=5, width=220, height=30)
# Label mit Aufschrift PIN
self.labelPIN = Label(master=self.rahmenPIN, background="white", text="PIN")
self.labelPIN.place(x=5, y=5, width=145, height=20)
# Entry für die PIN
self.entryPIN = Entry(master=self.rahmenPIN)
self.entryPIN.place(x=155, y=5, width=60, height=20)
...
def Button_Anzeigen_Click(self):
pin = int(self.entryPIN.get())
...
83
Eine GUI zur Bankwelt
#----------------------------------------------------------# Datenmodellobjekte
#----------------------------------------------------------from bank import *
bank = Bank()
bank.initBank()
#----------------------------------------------------------# GUI-Objekte
#-----------------------------------------------------------
from guibank import *
guibank = GUIBank(bank)
Aufgabe:
Welche Beziehungen bestehen zwischen den Objekten? Verdeutliche dies mit einem Objektund Klassendiagramm.
84
Zwei-Komponenten-Architektur
Das bisher entwickelte System zur Verwaltung von Bankkonten hat eine Zwei-KomponentenArchitektur. Die eine Komponente wird vom Datenmodell gebildet. Diese Komponente ist so
konzipiert, dass sie ohne eine grafische Benutzeroberfläche benutzt werden kann. Die andere
Komponente umfasst alle Klassen, die für die Erzeugung und Verwaltung der grafischen
Benutzeroberfläche benötigt werden. Da Objekte dieser Klassen u. a. für die Darstellung des
Datenmodells zuständig sind, dürfen sie Zugriff auf Datenmodell-Objekte haben.
#---------------------------------# Datenmodellobjekte
#---------------------------------from bank import *
bank = Bank()
bank.initBank()
#---------------------------------# GUI-Objekte
#---------------------------------from guibank import *
guibank = GUIBank(bank)
85
Trennung Datenmodell - GUI
Die Trennung zwischen Datenmodell und GUI ist ein Prinzip bei der Entwicklung von Systemen
mit grafischer Benutzeroberfläche, das hilft, klar strukturierte und gut wartbare Programme zu
erstellen: Während GUI-Objekte auf Objekte des Datenmodells zugreifen dürfen, ist der
umgekehrte Zugriff nicht erlaubt.
86
Model - View - Control
Bisher war das GUI-Objekt
sowohl für die Präsentation der
Daten auf der Benutzeroberfläche, als auch für die
Ereignisverarbeitung zuständig.
Diese beiden Zuständigkeiten
sollen jetzt aufgeteilt werden:
Einerseits soll es Präsentationsobjekte geben, die nur für die
Darstellung der Daten zuständig
sind, andererseits Steuerungsobjekte, die die Verbindungen
zwischen Präsentationsobjekten
und Datenmodellobjekten
herstellen und die
Ereignisverarbeitung festlegen.
Diese weitere Aufteilung der
Zuständigkeiten soll spätere
Änderungen oder Erweiterungen
des Softwaresystems erleichtern
und eine Wiederverwendbarkeit
einzelnen Komponenten
ermöglichen.
View
Control
Model
87
Model - View - Control
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
self.stand = 0.0
self.inhaber = None
...
class Kunde(object):
def __init__(self, name, vorname, pin):
self.name = name
self.vorname = vorname
self.pin = pin
self.konto= None
...
class Bank(object):
def __init__(self):
self.konten = []
self.kunden = []
self.naechsteKontoNr = 0
...
Model
88
Model - View - Control
from tkinter import *
class GUIBank(object):
def __init__(self, bank, \
cbAnzeigen, cbEinzahlen, cbAuszahlen, cbUeberweisen):
# Referenzattribute zum Datenmodell
self.bank = bank
self.cbAnzeigen = cbAnzeigen
self.cbEinzahlen = cbEinzahlen
self.cbAuszahlen = cbAuszahlen
self.cbUeberweisen = cbUeberweisen
# Erzeugung des Fensters
self.fenster = Tk()
self.fenster.title("Bank")
self.fenster.geometry('230x330')
...
# Button Anzeigen
self.buttonAnzeigen = Button(master=self.rahmenKonto, text="anzeigen", \
command=self.cbAnzeigen)
self.buttonAnzeigen.place(x=5, y=55, width=145, height=20)
...
# kein mainloop hier
View
89
Model - View - Control
from model_bank import *
Control
from view_bank import *
class Controler(object):
def __init__(self):
# Erzeugung der Datenmodell-Objekte
self.bank = Bank()
self.bank.initBank()
# Erzeugung und Initialisierung der GUI
self.guibank = GUIBank(self.bank, self.buttonAnzeigen, self.buttonEinzahlen, ...)
# Ereignisschreife
self.guibank.fenster.mainloop()
def buttonAnzeigen(self):
pin = int(self.guibank.entryPIN.get())
if self.bank.existiertPIN(pin):
kunde = self.bank.getKunde(pin)
self.guibank.labelKontonummer.config(text=str(kunde.konto.nr))
self.guibank.labelKontostand.config(text=str(kunde.konto.stand))
else:
self.guibank.labelKontonummer.config(text="")
self.guibank.labelKontostand.config(text="")
...
controler = Controler()
90
Model - View - Control
Aufgabe eines GUIBank-Objekts
ist es, die grafische
Benutzeroberfläche zu erzeugen.
View
Control
Aufgabe eines Model-Objekts ist
es, einen Aspekt der Miniwelt
abzubilden..
Model
Aufgabe eines Controler-Objekts
ist es, die Datenmodell- und
GUI-Objekte zu erzeugen und zu
verknüpfen.
Beachte, dass ein Controler-Objekt Zugriff auf Model- und View-Objekte hat.
Callback-Funktion
91
Eine Callback-Funktion (bzw. Rückruffunktion) ist eine Funktion, die einer anderen Funktion als
Parameter übergeben wird und von dieser unter gewissen Bedingungen aufgerufen wird.
class GUIBank(object):
Parameter für eine Callback-Funktion
def __init__(self, bank, cbAnzeigen, cbEinzahlen, cbAuszahlen, cbUeberweisen):
# Referenzattribute zum Datenmodell
self.bank = bank
self.cbAnzeigen = cbAnzeigen
self.cbEinzahlen = cbEinzahlen
self.cbAuszahlen = cbAuszahlen
self.cbUeberweisen = cbUeberweisen
# Erzeugung des Fensters
self.fenster = Tk()
self.fenster.title("Bank")
self.fenster.geometry('230x330')
...
# Button Anzeigen
self.buttonAnzeigen = Button(master=self.rahmenKonto, text="anzeigen", \
command=self.cbAnzeigen)
self.buttonAnzeigen.place(x=5, y=55, width=145, height=20)
...
Callback-Funktion
92
Eine Callback-Funktion (bzw. Rückruffunktion) ist eine Funktion, die einer anderen Funktion als
Parameter übergeben wird und von dieser unter gewissen Bedingungen aufgerufen wird.
class Controler(object):
def __init__(self):
# Erzeugung der Datenmodell-Objekte
self.bank = Bank()
self.bank.initBank()
Callback-Funktion
# Erzeugung und Initialisierung der GUI
self.guibank = GUIBank(self.bank, self.buttonAnzeigen, self.buttonEinzahlen, ...)
# Ereignisschreife
self.guibank.fenster.mainloop()
def buttonAnzeigen(self):
Callback-Funktion
pin = int(self.guibank.entryPIN.get())
if self.bank.existiertPIN(pin):
kunde = self.bank.getKunde(pin)
self.guibank.labelKontonummer.config(text=str(kunde.konto.nr))
self.guibank.labelKontostand.config(text=str(kunde.konto.stand))
else:
...
93
Strategie: Befragen
Das Objekt guiuhr nutzt eine Strategie, die man Befragen oder Polling nennt. Das Objekt
guiuhr weiß genau, wann sich das Datenmodell ändert (nach jedem Anklicken der
Schaltfläche) und besorgt sich die geänderten Daten zur Anzeige auf dem vorgesehenen Label.
class Uhr(object):
...
def tick(self):
if self.sekunden < 59:
self.sekunden = self.sekunden + 1
else:
self.sekunden = 0
if self.minuten < 59:
self.minuten = self.minuten + 1
else:
...
# Datenmodell
from uhr import *
uhr = Uhr()
# GUI-Objekt
from guiuhr import *
guiuhr = GUIUhr(uhr)
guiuhr.fenster.mainloop()
from tkinter import *
class GUIUhr(object):
def __init__(self, uhr):
# Referenzattribute zum Datenmodell
self.uhr = uhr
# Erzeugung des Fensters
...
# Button
self.buttonTick = Button(...,
command=self.Button_Tick_Click)
...
def Button_Tick_Click(self): Änderung
# Verarbeitung der Daten
self.uhr.tick()
Befragen
# Anzeige der Daten
uhrzeit = str(self.uhr.stunden) + ":" + \
str(self.uhr.minuten) + ":" + \
str(self.uhr.sekunden)
self.labelUhr.config(text=uhrzeit)
Strategie: Beobachten
94
Das Objekt guiuhr nutzt hier eine Strategie, die man Beobachten nennt. Das Objekt guiuhr
wird als registriertes beobachtendes Objekt jeweils benachrichtigt, wenn sich das Datenmodell
verändert hat.
import threading, time
class Timer(threading.Thread):
...
class Uhr(object):
def __init__(self):
...
self.aktiv = False
self.beobachter = None
def setBeobachter(self, beobachter):
self.beobachter = beobachter
...
def stoppen(self):
self.aktiv = False
def tick(self):
if self.sekunden < 59:
self.sekunden = self.sekunden + 1
else:
self.sekunden = 0
...
self.beobachter.anzeigeAktualisieren()
if self.aktiv:
self.timer = Timer(1, self.tick)
self.timer.start()
Änderung
def stellen(self, h, m, s):
self.stunden.setzen(h)
def ticken(self):
Beobachter
self.minuten.setzen(m)
self.aktiv = True
benachrichtigen
self.sekunden.setzen(s)
self.timer = Timer(1, self.tick)
self.beobachter.anzeigeAktualisieren()
self.timer.start()
Strategie: Beobachten
95
Beachte, dass die Klassen Uhr und GUIUhr so gestaltet sind, dass die Trennung zwischen
Datenmodell und GUI weiterhin Bestand hat. Erst zur Laufzeit wird der Beobachter des
Datenmodellobjekts festgelegt.
from tkinter import *
class GUIUhr(object):
def __init__(self, uhr):
# Referenzattribute zum Datenmodell
self.uhr = uhr
...
def Button_Start_Click(self):
# Verarbeitung der Daten
self.uhr.ticken()
# Datenmodell
from uhr import *
uhr = Uhr()
# GUI-Objekt
from guiuhr import *
guiuhr = GUIUhr(uhr)
# Beobachter festlegen
uhr.setBeobachter(guiuhr)
# Ereignisschleife starten
guiuhr.fenster.mainloop()
def Button_Stopp_Click(self):
# Verarbeitung der Daten
self.uhr.stoppen()
def anzeigeAktualisieren(self):
# Anzeige der Daten
uhrzeit = str(self.uhr.stunden)+":"+ str(self.uhr.minuten)+":" +str(self.uhr.sekunden)
self.labelUhr.config(text=uhrzeit)
96
Übungen
Aufgabe 1 (siehe www.inf-schule.de 1.12.7.8)
Die Klasse ModuloZaehler beschreibe Zähler, die modulo einer vorgegebenen Zahl zählen.
Entwickle eine einfache grafische Benutzeroberfläche, mit der man das Verhalten eines
Modulo-Zählers verdeutlichen kann.
97
Übungen
Aufgabe 2 (siehe www.inf-schule.de 1.12.7.8)
Ziel ist es, ein objektorientieres Datenmodell
mit einer grafische Benutzeroberfläche zu
verknüpfen. Als Miniwelt betrachten wir das
Spiel chuck a luck.
98
Übungen
Aufgabe 2 (siehe www.inf-schule.de 1.12.7.8)
Für die Benutzeroberfläche kannst du eine bereits entwickelte Implementierung übernehmen.
Implementiere das gesamte Programm so, dass eine klare Trennung zwischen Datenmodell
und GUI erkennbar ist.
99
Teil 6
Vererbung
100
Sparkonto
Ein Sparkonto ist ein Konto, bei dem das eingezahlte Geld mit einem bestimmten, mit der Bank
vereinbarten Zinssatz verzinst wird. Das folgende Klassendiagramm zeigt ein Sparkonto im
Vergleich zu einem normalen Konto.
Aufgabe:
Vergleiche die Klassendiagramme. Inwiefern unterscheiden sich die Attribute und Methoden
der beiden Klassen? Überleg dir auch, ob sich bestimmte Methoden evtl. anders verhalten.
Beachte, dass man das den Klassendiagrammen nicht entnehmen kann. Hinweis: Welche
Regelungen gibt es bei Auszahlungen von einem Sparkonto?
101
Sparkonto
Ein Sparkonto kann als spezielles Konto angesehen werden, das - im Vergleich zu einem
herkömmlichen Konto - nur in einigen Bestandteilen abgeändert worden ist.
Aufgabe:
Wie würde man ein solches Klassendiagramm wohl lesen?
102
Sparkonto
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
self.stand = 0
self.minimum = -1000.0
def einzahlen(self, betrag):
self.stand = self.stand + betrag
def auszahlen(self, betrag):
if self.stand - betrag >= self.minimum:
self.stand = self.stand - betrag
else:
print("Auszahlung nicht möglich!")
Aufgabe:
Analysiere die Implementierung der
Klasse Sparkonto. Alles klar?
Teste auch diese Implementierung.
class Sparkonto(Konto):
def __init__(self, nummer):
Konto.__init__(self, nummer)
self.zinssatz = None
self.minimum = 0
self.maxAuszahlung = 2000.0
def setZinssatz(self, zinssatz):
self.zinssatz = zinssatz
def auszahlen(self, betrag):
if betrag <= self.maxAuszahlung:
if self.stand - betrag >= self.minimum:
self.stand = self.stand - betrag
else:
print("Auszahlung nicht möglich!")
else:
print("Auszahlung nicht möglich!")
def zinsenGutschreiben(self):
zinsen = self.stand * (self.zinssatz / 100)
self.einzahlen(zinsen)
103
Vererbung
Vererbung beschreibt die Vorgehensweise, eine neue Klasse als Erweiterung einer bereits
bestehenden Klasse (oder mehrerer bereits bestehender Klassen) zu entwickeln. Die neue
Klasse wird auch Subklasse genannt, die bestehende Basisklasse oder Superklasse.
Basisklasse /
Superklasse
Subklasse
Übernehmen, ergänzen und überschreiben:
Beim Vererben übernimmt die Subklasse die Attribute und Methoden der Basisklasse.
Eine übernommene Methode kann dabei überschrieben (d. h. neu definiert) werden.
Die Subklasse kann dann noch zusätzliche Attribute und Methoden ergänzen.
104
Implementierung in Python
class Konto(object):
def __init__(self, nummer):
self.nr = nummer
self.stand = 0
self.minimum = -1000.0
Vererbung
class Sparkonto(Konto):
def __init__(self, nummer):
Konto.__init__(self, nummer)
self.zinssatz = None
Ergänzen
self.minimum = 0
Übernehmen
self.maxAuszahlung = 2000.0
def einzahlen(self, betrag):
self.stand = self.stand + betrag
def auszahlen(self, betrag):
if self.stand - betrag >= self.minimum:
self.stand = self.stand - betrag
else:
print("Auszahlung nicht möglich!")
def setZinssatz(self, zinssatz):
self.zinssatz = zinssatz
Überschreiben
def auszahlen(self, betrag):
if betrag <= self.maxAuszahlung:
if self.stand - betrag >= self.minimum:
self.stand = self.stand - betrag
else:
print("Auszahlung nicht möglich!")
else:
print("Auszahlung nicht möglich!")
def zinsenGutschreiben(self):
zinsen = self.stand * (self.zinssatz / 100)
self.einzahlen(zinsen)
105
Übungen
Aufgabe (siehe www.inf-schule.de 1.12.7.1 und 1.12.8.5)
Auf den folgenden Folien werden verschiedene Implementierungen einer grafischen
Benutzeroberfläche gezeigt.
Analysiere und erkläre, was in den jeweiligen Version unterschiedlich implementiert wird.
106
Übungen
# Datenmodell
from random import randint
from wuerfel import *
wuerfel = Wuerfel()
class Wuerfel(object):
# GUI
def __init__(self):
from tkinter import *
self.augen = 1
# Ereignisverarbeitung
def Wuerfel_Click():
def werfen(self):
# Verarbeitung der Daten
self.augen = randint(1, 6)
wuerfel.werfen()
# Anzeige der Daten
labelWuerfel.config(text=str(wuerfel.augen))
# Erzeugung des Fensters
fenster = Tk()
fenster.title("Würfel")
fenster.geometry('120x110')
# Eingabefeld für die Zahl
labelWuerfel = Label(master=fenster, text="1", background="#FBD975")
labelWuerfel.place(x=45, y=40, width=30, height=30)
# Button zum Auswerten
buttonWuerfel = Button(master=fenster, text="Würfel werfen", command=Wuerfel_Click)
buttonWuerfel.place(x=10, y=80, width=100, height=20)
# Aktivierung des Fensters
fenster.mainloop()
107
Übungen
from tkinter import *
# Datenmodell
from wuerfel import *
wuerfel = Wuerfel()
# GUI-Objekt
from guiwuerfel import *
guiwuerfel = GUIWuerfel(wuerfel)
guiwuerfel.fenster.mainloop()
class GUIWuerfel(object):
def __init__(self, wuerfel):
# Referenzattribute zum Datenmodell
self.wuerfel = wuerfel
# Erzeugung des Fensters
self.fenster = Tk()
self.fenster.title("Bank")
self.fenster.geometry('120x110')
# Eingabefeld für die Zahl
self.labelWuerfel = Label(master=self.fenster, text="1", background="#FBD975")
self.labelWuerfel.place(x=45, y=40, width=30, height=30)
# Button zum Auswerten
self.buttonWuerfel = Button(master=self.fenster, text="Würfel werfen",
command=self. Wuerfel_Click)
self.buttonWuerfel.place(x=10, y=80, width=100, height=20)
def Wuerfel_Click(self):
# Verarbeitung der Daten
self.wuerfel.werfen()
# Anzeige der Daten
self.labelWuerfel.config(text=str(self.wuerfel.augen))
108
Übungen
from tkinter import *
# Datenmodell
from wuerfel import *
wuerfel = Wuerfel()
# GUI-Objekt
from guiwuerfel import *
guiwuerfel = GUIWuerfel(wuerfel)
guiwuerfel.mainloop()
class GUIWuerfel(Tk):
def __init__(self, wuerfel):
# Referenzattribute zum Datenmodell
Tk.__init__(self)
self.wuerfel = wuerfel
# Erzeugung des Fensters
self.title("Würfel")
self.geometry('120x110')
# Eingabefeld für die Zahl
self.labelWuerfel = Label(master=self, text="1", background="#FBD975")
self.labelWuerfel.place(x=45, y=40, width=30, height=30)
# Button zum Auswerten
self.buttonWuerfel = Button(master=self, text="Würfel werfen",
command=self.Button_Wuerfel_Click)
self.buttonWuerfel.place(x=10, y=80, width=100, height=20)
def Button_Wuerfel_Click(self):
# Verarbeitung der Daten
self.wuerfel.werfen()
# Anzeige der Daten
self.labelWuerfel.config(text=str(self.wuerfel.augen))
109
Literaturhinweise
Es gibt eine Vielzahl von fachwissenschaftlichen Darstellungen zur
objektorientierten Modellierung und Programmierung. Hier wurden folgende
Lehrwerke benutzt:
- D. J. Barnes, M. Kölling: Objektorientierte Programmierung mit Java. Pearson Studium 2003.
- Helmut Balzert: Lehrbuch Grundlagen der Informatik. Spektrum Ak. Verlag 1999.
- Bernd Oestereich: Objektorientierte Softwareentwicklung. Oldenbourg 1998.
Dagegen gibt es nur wenige Schulbücher, die systematisch in die objektorientierte
Programmierung einführen, z. B.:
- Siegfried Spolwig: Objektorientierung im Informatikunterricht. Dümmler-Verlag
1997.
- P. Damann, J. Wemßen: Objektorientierte Programmierung mit Delphi, Band 2.
Klett-Verlag 2003.
Viele interessante Artikel mit Unterrichtsvorschlägen bzw. fachdidaktischen
Auseinandersetzungen findet man in der Zeitschrift LOG IN. Das Themenheft
128/129 ist speziell dem Thema „Objektorientiertes Modellieren und
Programmieren“ gewidmet.
...
110
Literaturhinweise
Im Internet findet man ebenfalls sehr viele schulgerechte Darstellungen der
objektorientierten Modellierung und Programmierung, z. B:
http://informatikag.bildung-rp.de/
Die AG-Informatik des LMZ in RLP stellt u. a. auch Fortbildungsmaterialien zu
diesem Thema bereit.
http://hsg.region-kaiserslautern.de/faecher/inf/index.php
Auf der Homepage des HSG in Kaiserslautern findet man Unterrichtsmaterialien und
Links zu weiteren interessanten Seiten.
...
Die Darstellung hier orientiert sich an den Materialien auf den Webseiten:
http://www.inf-schule.de