Konzepte objektorientierter Programmierung

of 110 /110
Konzepte objektorientierter Programmierung Klaus Becker 2009

Embed Size (px)

description

Konzepte objektorientierter Programmierung. Klaus Becker 2009. Objektorientierung. " Objektorientierung ist die derzeitige Antwort auf die gestiegene Komplexität der Softwareentwicklung." Oestereich: Objektorientierte Software-Entwicklung. Teil 1. Objekte. S. - PowerPoint PPT Presentation

Transcript of Konzepte objektorientierter Programmierung

  • Konzepte objektorientierter ProgrammierungKlaus Becker 2009

  • Objektorientierung"Objektorientierung ist die derzeitige Antwort auf die gestiegene Komplexitt der Softwareentwicklung."Oestereich: Objektorientierte Software-Entwicklung

  • Teil 1Objekte

  • Verwaltung von BankkontenZiel 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.

  • Verwaltung von BankkontenWesentliche zu verwaltende Daten erkennt man auf einem Kontoauszug.Kontostand

    Kontonummer

    Kontoinhaber

    auszahlen

    einzahlen

    auszahlen

    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 verfgbar ist. Von einem Bankkonto kann man Geldbetrge auszahlen, man kann aber Geldbetrge auf ein Konto einzahlen.

  • Objektorientierter ModellierungsansatzSo wie die zu verwaltende Welt aus Objekten - hier Konten - besteht, so soll das Verwaltungssystem aus Softwareobjekten aufgebaut werden.Softwareobjekt

  • Softwareobjekt in Aktion>>> konto = Konto(234126)>>> konto.nr234126>>> konto.stand0>>> konto.stand = 2380.0>>> konto.stand2380.0>>> konto.auszahlen(450.0)>>> konto.stand1930.0>>> konto.einzahlen(1000.0)>>> konto.stand2930.0>>> konto.auszahlen(800.0)>>> konto.stand2130.0Wenn man das Programm konto.py ausfhrt, dann lsst sich folgender Python-Dialog fhren. Probiere das einmal aus.

  • ObjekteEin Objekt ist eine Einheit, die Daten mit Hilfe von Attributen verwalten und Operationen zur Verarbeitung der verwalteten Daten mit Hilfe von Methoden ausfhren kann.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 ausgefhrt, wenn das betreffende Objekt Operationen ausfhrt. Ein Objekt befindet sich stets in einem bestimmten Zustand. Der aktuelle Objektzustand wird durch die aktuellen Werte der Attribute festgelegt.Objekt

    Attribute - Attributwerte

    Ausfhrung einer Methode

    Objektdiagramm

  • ObjekteObjekt

    Attribute - Attributwerte

    Ausfhrung einer Methode

    Zugriff auf Attribute:konto.stand = 2380.0objekt.attributAktivierung von Methoden:konto.einzahlen(1000.0)objekt.methode

  • bungenAufgabe 1 (siehe www.inf-schule.de 1.12.1.4)Lade die Datei wuerfel.txt herunter (benenne sie in wuerfel.py um) und fhre einen Python-Dialog analog zum folgenden:>>> w = Wuerfel()>>> w.augen1>>> w.werfen()>>> w.augen6(a) Was leistet das Attribut augen des Objekts w, was die Methode werfen()?(b) Beschreibe den gezeigten Ablauf mit Hilfe von Objektdiagrammen.

  • Teil 2Klassen

  • Ein Bauplan fr Konto-Objekteclass 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): # ...Aufgabe 1:Analysiere diese Klassendeklaration und ergnze den fehlenden Teil # ....berprfen kannst du deinen Lsungsvorschlag, indem du die Klassendeklaration unter einem geeigneten Namen (z. B. konto.py) abspeicherst und ausfhrst. Wenn du alles richtig gemacht hast, dann sollte z. B. der oben gezeigte Python-Dialog mglich sein.>>> k1 = Konto(5)>>> k1.nr5>>> k1.stand0>>> k1.einzahlen(100.0)>>> k1.stand100.0

  • Ein Bauplan fr Konto-Objekteclass 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): # ...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.>>> k1 = Konto(5)>>> k1.einzahlen(1000.0)>>> k2 = Konto(8)>>> ...

  • KlassenEine Klasse ist ein Bauplan fr Objekte. Dieser Bauplan legt genau fest, welche Attribute die zu konstruierenden Objekte haben sollen und welche Methoden sie ausfhren knnen sollen.Objektdiagramm

    Ein Objekt (als Exemplar einer Klasse) ist eine Einheit, die nach dem Bauplan der zugeordneten Klasse erzeugt wurde. Ein Objekt verfgt somit ber die Attribute, die in der Klasse festgelegt sind. Diesen Attributen knnen - im Unterschied zur Klasse - Attributwerte zugewiesen werden. Ein Objekt kann zudem smtliche Methoden der Klasse ausfhren. Ausgenommen bleibt hier nur die Methode, deren Name mit dem Klassennamen bereinstimmt (s. u.). Objekte knnen mit Namen versehen werden, ber die sie dann gezielt angesprochen werden knnen.Klassendiagramm

  • Konstruktor / DestruktorZur Erzeugung von Objekten verfgt eine Klasse ber eine spezielle Methode, die sogenannte Konstruktormethode.Zur Vernichtung von Objekten verfgt eine Klasse ber eine sogenannte Destruktormethode.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 trgt. Oft wird diese spezielle Methode in Klassendiagrammen aber auch weggelassen. Beachte, dass eine Konstruktormethoden keine Methode ist, die ein Objekt ausfhren kann.Destruktormethoden werden in der Regel in Klassendiagrammen weggelassen.Konstruktor

  • Klassendeklaration in PythonKlassenname

    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 - betragDoppelpunktEinrckungSchlsselwortOberklasse

    AttributeAttributeKonstruktorMethodeMethodeReferenz auf Objekt

  • Objekterzeugung in Pythonclass 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(5)>>> k2 = Konto(8)>>> k1.nr5>>> k1.stand0>>> k2.nr8>>> k2.stand0>>> k1.__dict__{'nr': 5, 'stand': 0}>>> k2.__dict__{'nr': 8, 'stand': 0}>>> k = Konto(5)>>> k.stand0.0>>> del k>>> k.standTraceback (most recent call last): File ...NameError: name 'k' is not defined>>> Klassendeklaration

    Erzeugung eines Objekts

    Vernichtung eines Objekts

    Inspektion eines Objekts

  • bungenAufgabe 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 wrfele hiermit solange, bis mindestens einer der Wrfel eine 6 liefert.

  • bungenAufgabe 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.

  • bungenAufgabe 3 (siehe www.inf-schule.de 1.12.2.5)Wenn man modulo einer vorgegebenen Zahl (man nennt sie auch Modul) zhlt, 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 zhlt, 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 zhlt, 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 ermglicht. Implementiere die Klasse und teste sie mit geeigneten Python-Dialogen. >>> z = ModuloZaehler(3)>>> z.modul3>>> z.stand0>>> z.weiterzaehlen()>>> z.stand1>>> z.weiterzaehlen()>>> z.stand2>>> z.weiterzaehlen()>>> z.stand0>>> z.zurueckzaehlen()>>> z.stand2>>> z.nullsetzen()>>> z.stand0

  • bungenAufgabe 5 (siehe www.inf-schule.de 1.12.2.5)Die Klasse Schlange kann man verwenden, um Warteschlangen zu simulieren. Erlutere, was die Methoden der Klasse Schlange bewirken. Verdeutliche deine Erluterungen 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

  • bungenAufgabe 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>>> k1 = Konto()>>> k1.nr0>>> k1.stand0>>> k2 = Konto(1)>>> k2.nr1>>> k2.stand0>>> k3 = Konto(2, 1000.0)>>> k3.nr2>>> k3.stand1000.0>>> k4 = Konto(betrag=400.0)>>> k4.nr0>>> k4.stand400.0Erklre, wie die jeweiligen Attributwerte der Objekte zustande kommen.

  • Teil 3Verwaltung von Objekten

  • Objekte und ihre IdentittPython-DialogAufgabe:Was verbirgt sich wohl hinter der Identittsnummer eines Objekts?Prfe mit geeigneten Python-Dialogen, ob sich die Identittsnummer eines Objekts ndert, wenn sich der Zustand eines Objekts beim Ausfhren einer Methode ndert. >>> k1 = Konto(3)>>> k1

    >>> id(k1)20305520>>> hex(20305520)'0x135d670'>>> k2 = Konto(4)>>> id(k2)20307184

  • Konto kopieren?Python-DialogAufgabe:Stell Vermutungen auf, was anstelle der drei Fragezeichen jeweils steht. Teste, ob deine Vermutungen stimmen. Kannst du dir die Ergebnisse erklren? Benutze auch den id-Operator, um Einsicht ber die verwalteten Objekte zu erhalten.>>> k1 = Konto(6)>>> k2 = k1>>> k1.stand???>>> k2.stand???>>> k2.einzahlen(100.0)>>> k1.stand???>>> k2.stand???>>> k2 = Konto(7)>>> k1.stand???>>> k2.stand???>>>

  • Identitt von Objekten(Daten-) Objekte haben - analog zu Objekten unserer Lebenswelt - ebenfalls eine Identitt. Zur eindeutigen Identifizierung werden sie mit Identittsnummern versehen.

    Verschiedene Objekte unterscheiden sich in ihrer Identittsnummer. Sie knnen aber durchaus denselben Objektzustand haben.

    Ein Objekt behlt whrend seiner Lebensdauer immer die einmal vergebene Identittsnummer. Auch wenn sich der Zustand des Objekts verndert, so bleibt doch die Identittsnummer des Objekts bestehen.

    Hufig verwendet hierzu man eine Adresse im Speicher des Rechners als Identittsnummer. Die Identittsnummer 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 natrlich voraus, dass Objekte im Speicher nicht hin und her wandern, sondern dass der einmal zugeteilte Speicherbereich whrend der Lebensdauer eines Objekts bestehen bleibt. Wir gehen im Folgenden von dieser Vorstellung aus.

  • Zeiger / ReferenzenEine Variable ist ein Name, der (in der Regel) mit einem Objekt verknpft ist. Wenn eine Variable ein (Daten-) Objekt verwaltet, dann verwaltet es die Speicheradresse (bzw. Identitsnummer) 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.

  • Zuweisungen bei Zeigervariablenk1 = Konto(6)k2 = k1k2.einzahlen(100.0)k2 = Konto(7)

  • Objekte in PythonVernderbares ObjektUnvernder-bares ObjektSeiteneffektkein Seiteneffektfrom 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))def null(zahl): print(id(zahl)) zahl = 0.0 print(id(zahl))

    z = 100.0print(z)print(id(z))null(z)print(z)print(id(z))Python unterscheidet zwischen vernder-baren und unvernderbaren Objekten.

  • bungenAufgabe 1 (siehe www.inf-schule.de 1.12.3.5)Wenn man den Objektbezeichner vom Python-Interpreter auswerten lsst, dann wird der vom Bezeichner verwaltete Wert angezeigt. Warum zeigt der Python-Dialog, dass hier Zeiger verwaltet werden?>>> k1 = Konto(6)>>> k2 = k1>>> k1

    >>> k2

    >>> k2 = Konto(8)>>> k2

    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

  • bungenAufgabe 2 (siehe www.inf-schule.de 1.12.3.5)Jedes Objekt wird zur Identifierung mit einer eindeutigen Identittsnummer versehen. Mit Hilfe des id-Operators lsst sich diese Identittsnummer in Python ermitteln. Was zeigt der abgebildete Python-Dialog?>>> k1 = Konto(6) >>> k2 = k1 >>> id(k1) 31153488 >>> id(k2) 31153488 >>> k2 = Konto(8) >>> id(k2) 31096624 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

  • bungenAufgabe 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 erklre das unterschiedliche Verhalten.def mitNeuemErsten(liste, element): hilf = [element] + liste[1:] return hilf

    L = [1, 2, 3]M = mitNeuemErsten(L, 0)print(L)print(M)def mitNeuemErsten(liste, element): liste[0] = element return liste

    L = [1, 2, 3]M = mitNeuemErsten(L, 0)print(L)print(M)

  • Teil 4Modularisierung und Datenkapselung

  • Konto berziehen>>> k = Konto(9)>>> k.stand = 600.0>>> k.stand600.0>>> auszahlungsbetrag = 2750.0>>> k.stand = k.stand - auszahlungsbetrag>>> k.stand-2150.0Implementierung der KlasseNutzung der Klasse Ein Konto soll hchstens um 1000 Euro berzogen werden drfen.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 mglich!")Aufgabe 1:Warum ist dieser Dialog nicht im Sinne des Bankkontenverwaltungssystems?

  • Konto berziehenfrom konto import Kontok = Konto(9)# Testlaufk.einzahlen(600.0)print(k.getStand())auszahlungsbetrag = 2750.0k.auszahlen(auszahlungsbetrag)print(k.getStand())Schnittstelle zur KlasseNutzung der Klasse Die Entwickler der Klasse Konto verffentlichen folgende Schnittstelle dieser Klasse:Aufgabe 2:Warum macht es hier Sinn, die Attribute der Klasse Konto nicht zu verffentlichen und eine Vernderung von Attributwerten nur ber verffentlichte Merhoden zu erlauben?Aufgabe 3:Im Testprogramm wird die Methode getStand benutzt, die in der Schnittstelle vorgesehen ist. Was soll diese Methode leisten? Ergnze die oben gezeigte Implementierung der Klasse Konto um die noch fehlenden Methoden und fhre das Testprogramm aus.

  • Modularisierung"Unsere Partyzelte knnen in verschiedenen Gren aufgebaut werden. Da die Partyzelte und Festzelte aus Modulen bestehen, ist es sehr einfach, sie zu erweitern. Die Abbildung zeigt ein mgliches Kombinationsbeispiel der Module."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.Ein Softwaremodul ist eine in sich abgeschlossene Einheit, die man vielfltig bei Problem-lsungen einsetzen kann. Es reicht dabei zu wissen, welche Operationen die Einheit dem Benutzer zur Verfgung stellt. Wie die Operationen programmiert sind, muss man dagegen nicht wissen.Grundidee der objektorientierten Modularisierung ist es, Softwaremodule als Klassen zu konzipieren .

  • Modularisierung in Pythonfrom konto import Kontok = Konto(9)# Testlaufk.einzahlen(600.0)print(k.getStand())auszahlungsbetrag = 2750.0k.auszahlen(auszahlungsbetrag)print(k.getStand())from konto import *k = Konto(9)# Testlaufk.einzahlen(600.0)print(k.getStand())auszahlungsbetrag = 2750.0k.auszahlen(auszahlungsbetrag)print(k.getStand())import kontok = konto.Konto(9)# Testlaufk.einzahlen(600.0)print(k.getStand())auszahlungsbetrag = 2750.0k.auszahlen(auszahlungsbetrag)print(k.getStand())Der Name "Konto" wird in den aktuellen Namensraum bernommen.

  • Geheimnisprinzip / DatenkapselungBeim Autobau wird somit - zumindest in bestimmten Bereichen - das Geheimnisprinzip angewandt. Bestimmte Eigenschaften des Motors knnen nur ber speziell hierfr vorgesehene Schnittstellen ermittelt werden. So kann der aktuelle lstand nur an einem hierfr vorgesehenen Messstab abgelesen werden. nderungen am aktuellen Motorzustand knnen direkt ebenfalls nur an bestimmten hierfr vorgesehenen Stellen vorgenommen werden. Motorl lsst sich nur in die hierfr vorgesehene ffnung einfllen. Alles weitere ber das Innere des Motors bleibt fr den normalen Autofahrer unzugnglich und in diesem Sinne geheim.Bei der objektorientierten Software-Entwicklung geht man vllig 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 mglich ist. Jeder Zugriff auf interne Daten und jede Vernderung von internen Daten darf nur ber spezielle, hierfr vorgesehene Methoden erfolgen. Man nennt diese Vorgehensweise auch Datenkapselung.

  • Zugriffsrechte / ZugriffsmethodenUm interne Daten kapseln zu knnen, werden Zugriffrechte festgelegt. Der Entwickler einer Klasse hat die Mglichkeit, Attribute und Methoden einer Klasse als ffentlich oder privat zu deklarieren. Lesende und schreibende Zugriffe auf Attribute bzw. Methoden eines Objekts sind nur mglich, wenn diese ffentlich sind. Private Attribute bzw. Methoden knnen dagegen nur bei der Implementierung der betreffenden Klasse benutzt werden.Im Klassendiagramm werden die Zugriffsrechte auf die Attribute und Methoden mit Hilfe der Symbole + (fr ffentlich) und - (fr privat) festgelegt.Verfolgt man die Strategie, alle Attribute als privat zu deklarieren, so besteht keine Mglichkeit, 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.

  • Zugriffsrechte in PythonEin 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.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 mglich!")

    def getStand(self): return self.__stand

    def setStand(self, stand): if stand >= self.__minimum: self.__stand = stand else: print("Initialisierung nicht mglich!") # ...

  • Datenkapselung in PythonWie 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__ verrt, woran das liegt. Ein Aufruf wie k.__dict__ listet smtliche Attribute mit den zugehrigen 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 mglich 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.>>> k = Konto(3)>>> k.__standTraceback (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__stand0

  • Datenkapselung in PythonEin erster Zugriff auf das private Attribut __stand scheitert. Dann aber ist es - entgegen aller Zugriffslogik - scheinbar mglich, dem privaten Attribut __stand einen Wert zuzuweisen. Der Aufruf k.__dict__ erklrt 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.>>> k = Konto(3)>>> k.__standTraceback (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.__stand100.0>>> k.__dict__{_Konto__minimum': -1000.0, '_Konto__nr': 3, '_Konto__stand': 0, '__stand': 100.0}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 einfhren und nutzen. Nur in begrndeten Ausnahmefllen werden wir von dieser Vereinbarung abweichen.

  • SchnittstellenDie Schnittstelle einer Klasse liefert alle Informationen, die man bentigt, um die Klasse benutzen zu knnen. Hierzu gehrt eine genaue Beschreibung aller ffentlichen Attribute und Methoden der Klasse. Fr jedes Attribut bentigt man den erwarteten Datentyp, fr jede Methode die Signatur (d. h. die genaue Festlegung der Parametertypen und bei Funktionen des Rckgabetyps) 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 betrgt 0, der Wert des Attributs minimum betrgt -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.

  • bungenAufgabe 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)from wuerfel import *# Wrfelprogrammw = Wuerfel()w.werfen()versuche = 1while w.augen != 6: w.werfen() versuche = versuche + 1print("Versuche:", versuche)(a) Was leistet das folgende Programm, das das Modul Wuerfel als Baustein benutzt?(b) Es soll getestet werden, wie oft man drei Wrfel werfen muss, bis mindestens einer eine 6 liefert. Entwickle ein geeignetes Simulationsprogramm, das die Klasse Wuerfel als Baustein benutzt.

  • bungenAufgabe 2 (siehe www.inf-schule.de 1.12.4.8)Folgende Klassen sollen als Bausteine zur Simulation des Spiels "chuck a luck" zur Verfgung gestellt werden:>>> k = Konto(100)>>> s = Spielzahl()>>> wA = Wuerfel()>>> wB = Wuerfel()>>> wC = Wuerfel()>>> k.abheben(1)>>> k.stand99>>> s.setzen(3)>>> s.zahl3>>> wA.werfen()>>> wB.werfen()>>> wC.werfen()>>> wA.augen3>>> wB.augen6>>> wC.augen2>>> k.einzahlen(2)>>> k.stand101(a) Implementiere diese Klassen. Mit Hilfe dieser Bausteine sollen dann Python-Dialoge wie der folgende mglich sein.(b) Mit Hilfe eines Simulationsprogramms soll ermittelt werden, ob das chuck-a-luck-Spiel fair ist.

  • bungenAufgabe 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.... def vollstaendigKuerzen(self): # ggT von Zhler und Nenner best. x = self.zaehler y = self.nenner while y > 0: h = x % y x = y y = h ggt = x # krzen self.kuerzen(ggt)

    def add(self, b): x1 = self.zaehler x2 = self.nenner y1 = b.zaehler y2 = b.nenner z1 = x1*y2 + x2*y1 z2 = x2*y2 self.zaehler = z1 self.nenner = z2 self.vollstaendigKuerzen()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...(c) Fge der Klasse Bruch weitere Operationen hinzu und teste diese Erweiterung.

  • bungenAufgabe 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()

  • bungenAufgabe 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. Erklre, was hier schiefluft.(b) Warum ist es so schwierig, Flchtigkeitsfehler 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

  • Teil 5Beziehungen

  • Verwaltung des KontoinhabersDer Kontoinhaber soll jetzt ebenfalls mitverwaltet werden. Hierzu muss das Objektmodell erweitert werden. Mehrere Vorschlge stehen zur DiskussionAufgabe:Vergleiche die folgenden Vorschlge.Vorschlag 1:Vorschlag 2:

  • Verwaltung des KontoinhabersAufgabe:Welche Nachteile zeigen sich bei Vorschlag 2, wenn es mehrere Konten und mehrere Kunden gibt? Vergleiche Vorschlag 2 mit Vorschlag 3.Vorschlag 3:Vorschlag 2:

  • Verwaltung des KontoinhabersAufgabe:Erklre, wie die Objektkonstellation aus Vorschlag 3 hier realisiert wird. Stell auch eine Vermutung auf, was das Testprogramm auf dem Bildschirm ausgibt.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 = vornamefrom konto_kunde import *# Erzeugung der Objektekonto1 = Konto(5)konto2 = Konto(11)konto2.stand = 200.0kunde1 = Kunde("Mller", "Adriana")kunde2 = Kunde("Meier", "Anatol")konto1.inhaber = kunde2konto2.inhaber = kunde1# Ausgabenprint("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)

  • BeziehungWenn ein Objekt ber einen Zeiger (eine Referenz) Zugriff auf ein anderes Objekt hat, so liegt eine (gerichtete) Beziehung zwischen den Objekten vor.Objektdiagramm

    Klassendiagramm

    Mit Hilfe eines Aufrufs wie z.B. konto1.inhaber kann das Konto-Objekt konto1 auf Daten des zugeordneten Kunde-Objekts zugreifen, z.B. mit konto1.inhaber.name auf das entsprechende Attribut. Das Konto-Objekt konto1 hat somit Zugriff auf ein Kunde-Objekt, z.B. kunde2. Man sagt auch, dass das Konto-Objekt konto1 in Beziehung zum Kunde-Objekt kunde2 steht.

  • BeziehungsmusterMuster: Objekt der Klasse A kennt Objekt der Klasse BMuster: Objekt der Klasse A kennt Objekt der Klasse B und umgekehrtMuster: Objekt der Klasse A kennt mehrere Objekte der Klasse BMuster: Objekt der Klasse A erzeugt Objekt der Klasse B

  • Implementierung von BeziehungenMuster: Objekt der Klasse A kennt Objekt der Klasse Bclass 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 = vornamefrom bank0 import *# Erzeugung der Objektekonto1 = Konto(5)konto2 = Konto(11)konto2.stand = 200.0kunde1 = Kunde("Mller", "Adriana")kunde2 = Kunde("Meier", "Anatol")konto1.inhaber = kunde2konto2.inhaber = kunde1

  • Implementierung von BeziehungenMuster: Objekt der Klasse A kennt Objekt der Klasse B und umgekehrtclass 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 = Nonefrom bank1 import *# Erzeugung der Objektekonto1 = Konto(5)konto2 = Konto(11)konto2.stand = 200.0kunde1 = Kunde("Mller", "Adriana")kunde2 = Kunde("Meier", "Anatol")konto1.inhaber = kunde2konto2.inhaber = kunde1kunde1.konto = konto2kunde2.konto = konto1

  • Implementierung von BeziehungenMuster: Objekt der Klasse A kennt mehrere Objekte der Klasse Bclass 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 = []

    def kontoHinzufuegen(self, konto): self.konten = self.konten + [konto]from bank2 import *# Erzeugung der Objektekonto1 = Konto(5)konto2 = Konto(11)konto2.stand = 200.0konto3 = Konto(19)konto3.stand = 150.0konto4 = Konto(21)konto4.stand = -50.0kunde1 = Kunde("Mller", "Adriana")kunde2 = Kunde("Meier", "Anatol")konto1.inhaber = kunde2konto2.inhaber = kunde1konto3.inhaber = kunde1konto4.inhaber = kunde1kunde1.kontoHinzufuegen(konto2)kunde1.kontoHinzufuegen(konto3)kunde1.kontoHinzufuegen(konto4)kunde2.kontoHinzufuegen(konto1)Liste

  • Implementierung von BeziehungenMuster: Objekt der Klasse A erzeugt Objekte der Klasse Bclass 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 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 + 1from bank3 import *from random import *# Erzeugung der Objektebank = Bank()for i in range(8): bank.erzeugeKonto()for konto in bank.konten: konto.einzahlen(float(randint(0, 100)))

  • Operationen als DiensteObjekte knnen (in aller Regel) bestimmte Operationen mit den von ihnen verwalteten Daten ausfhren. Die Ausfhrung einer Operationen wird als Dienst anderen Objekten zur Verfgung gestellt. Andere Objekte knnen den zur Verfgung 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.

  • Interaktion zwischen ObjektenWenn das Bank-Objekt den Dienst "ueberweisen" ausfhrt, dann schickt es zunchst eine Nachricht auszahlen(...) an das betreffende Konto-Objekt und anschlieend eine Nachricht einzahlen(...) an das andere betreffende Konto-Objekt. Das Bank-Objekt interagiert also hier mit zwei Konto-Objekten. Dies ist deshalb mglich, weil das Bank-Objekt gem Klassendiagramm oben in Beziehung zu den Konto-Objekten steht.Die Analogien zur Lebenswelt ermglichen es, die Ausfhrung objektorientierter Programme in einem Rollenspiel zu verdeutlichen, bei dem Personen die Rolle von Objekten bernehmen.

  • Interaktion zwischen ObjektenWenn 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 Verfgung gestellten Operationen. Das Versenden von Nachrichten wird als Interaktion zwischen Objekten gedeutet. Voraussetzung fr eine Interaktion zwischen Objekten ist, dass diese miteinander in Beziehung stehen.Wenn das Bank-Objekt den Dienst "ueberweisen" ausfhrt, dann schickt es zunchst eine Nachricht auszahlen(...) an das betreffende Konto-Objekt und anschlieend eine Nachricht einzahlen(...) an das andere betreffende Konto-Objekt. Das Bank-Objekt interagiert also hier mit zwei Konto-Objekten. Dies ist deshalb mglich, weil das Bank-Objekt gem Klassendiagramm oben in Beziehung zu den Konto-Objekten steht.Sequenzdiagramm

  • bungenAufgabe 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

  • bungenAufgabe 2 (siehe www.inf-schule.de 1.12.5.6)Ein Kunde soll neben einem Erstkonto auch ein Zweitkonto haben knnen.(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).

  • bungenAufgabe 3 (siehe www.inf-schule.de 1.12.5.6)In der freien Enzyklopdie Wikipedia werden Artikel zu Stichwrtern von Benutzern verfasst. Eine erste Modellierung der Klassen Artikel und Benutzer knnte 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.

  • bungenAufgabe 3 (siehe www.inf-schule.de 1.12.5.6)Das Modell soll so erweitert werden, dass Artikel von Benutzern berarbeitet werden knnen:(b) Implementiere das erweiterte Modell und erzeuge eine typische Objektsituation. Verdeutliche die erzeugte Objektsituation auch mit einem Objektdiagramm.(c) Wie msste man die Klasse Benutzer erweitern, wenn hier auch die Mitarbeit an Artikeln mit einem Referenzattribut erfasst werden soll.

  • bungenAufgabe 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 ausgefhrt werden kann.from geometrie import *# Punktep1 = 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 Figurhaus_nikolaus = Figur()haus_nikolaus.hinzufuegen(rechteck)haus_nikolaus.hinzufuegen(dreieck)# Punkt verschieben und ausgebenp1.verschieben(4, 1)...

  • Teil 6Miniwelt und Datenmodell

  • Bankwelt im ComputerDie Bankwelt mit bestimmten Gegenstnden (Kunden, Konten, ...) und Vorgngen (Ein-, Auszahlungen, ...) soll in einem Programm geeignet erfasst werden.

  • Bankwelt im ComputerAufgabe:Welche Objekte sind fr welche Aufgaben zustndig?Welche Vereinfachungen sind bei dieser Beschreibung einer Bankwelt vorgenommen?

  • Bankwelt im Computerfrom bank import *bank = Bank()# Konten erffnenbank.kontoEroeffnen("Mller", "Adriana", 2101)bank.kontoEroeffnen("Meier", "Adrian", 1507)bank.kontoEroeffnen("Schuster", "Christiane", 1313)bank.kontoEroeffnen("Weber", "Alexander", 2276)# Ausgabe der kontenfor 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()# Transaktionprint("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 Vorgnge der Bankwelt durchzuspielen. Das folgende Python-Testprogramm zeigt, wie das gehen knnte.

  • MiniweltMit Miniwelt bezeichnen wir den Weltausschnitt / Gegenstandsbereich, der dem zu entwickelnden Programm (Software-System) zu Grunde liegt.

  • DatenmodellEin Modell ist eine vereinfachende Darstellung einer Miniwelt, die (fr einen bestimmten Zweck ausgewhlte) Teilaspekte der Miniwelt strukturgetreu beschreibt.Aufgabe eines objektorientiertes Datenmodells ist es, die Struktur der Miniwelt mit Hilfe von Objekten und deren Beziehungen zu beschreiben.

  • ZustndigkeitenBei der Entwicklung komplexer Software-Systeme ist es gnstig, dieses System aus mehreren Objekten zusammenzusetzen. Jedes Objekt sollte dabei fr einen bestimmten Aufgabenbereich zustndig sein. Ein solches System aus Objekten mit klar umgrenzten Zustndigkeiten erhht die Durchschaubarkeit des gesamten Software-Systems und erleichtert es, das System nachtrglich abzundern oder zu erweitern.Objekt der Klasse Kunde: verwaltet die KundendatenObjekt der Klasse Konto: verwaltet die Kontodaten; fhrt Ein- und Auszahlungen ausObjekt der Klasse Bank: erzeugt und verwaltet alle Kunde-Objekte und Konto-Objekte; veranlasst alle Geldtransfers zwischen Konten; ...

  • UMLUML steht fr uniform modeling language und ist eine normierte Bildsprache, mit der man objektorientierte Modelle beschreiben kann.Sequenzdiagramm

    Klassendiagramm

    Objektdiagramm

  • UML-EditorViolet ist ein sehr einfaches, frei nutzbares Werkzeug zur Erstellung von UML-Diagrammen. siehe: http://www.horstmann.com/violet/

  • bungenAufgabe 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 Verfgung stellen.(a) Skizziere ein Objektdiagramm zur Miniwelt chuck-a-luck.(b) Woran erkennt man im Klassendiagramm, dass das Spiel-Objekt fr die Erzeugung der weiteren Objekte zustndig ist? Welche weiteren Zustndigkeiten hat das Spiel-Objekt?(c) Implementiere dieses Modell. Teste es wie folgt. from chuckaluck import *# Erzeugung der Objektespiel = Spiel()# Durchfhrung eines Spielsspiel.einsatzZahlen()spiel.spielzahlSetzen(5)spiel.wuerfelWerfen()spiel.gewinnAuszahlen()# Ausgabe der Spielprint("Wrfel A:", spiel.wuerfelA.augen)...

  • bungenAufgabe 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 Musepopulation aus ... (siehe Einstieg - Musepopulation) 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 berprfen..(d) Was msste am Datenmodell verndert werden, wenn man die Population aus ... (siehe Miniprojekt) modellieren wollte?

  • bungenAufgabe 3 (siehe www.inf-schule.de 1.12.6.6)Ein Zahlenschloss bestehe aus drei Einstellrdern, mit denen die Ziffern der Schlsselzahl einzeln eingestellt werden knnen. Hat man die Schlsselzahl richtig getroffen, dann ist das Schloss offen.Entwickle ein objektorientiertes Datenmodell, das die vorliegende Miniwelt mglichst strukturgetreu beschreibt. Stell das Datenmodell auch mit Hilfe von UML-Diagrammen dar.Implementiere und teste das Datenmodell.

  • Teil 7Datenmodell und grafische Benutzeroberflche

  • Eine GUI zur BankweltDas bisher entwickelte Programm zur Verwaltung von Bankkonten soll um eine grafische Benutzeroberflche erweitert werden. Der Benutzer soll die Mglichkeit haben, wie an einem Terminal in der Bank seine Bankgeschfte zu erledigen. Am Terminal kann man sich den aktuellen Kontostand anzeigen lassen, Geldbetrge ein- und auszahlen und auch berweisungen vorzunehmen.

  • Eine GUI zur BankweltAufgabe: Das gezeigte Programm (siehe www.inf-schule.de ...) enthlt zwar noch Implementierungslcken, ist aber nichtsdestotrotz lauffhig. Teste zunchst das Programm. Mache dich auch mit dem Quelltext vertaut. Analysiere insbesondere die schon implementierten Ereignisverarbeitungsprozeduren. Implementiere die noch fehlenden Implementierungen.#-----------------------------------------------------------# Datenmodell#-----------------------------------------------------------

    from bank import *bank = Bank()bank.initBank()

    #-----------------------------------------------------------# GUI#-----------------------------------------------------------

    from tkinter import *

    # ... Prozeduren zur Ereignisverarbeitung

    # Erzeugung des Fenstersfenster = Tk()fenster.title("Bank")fenster.geometry('230x330')...

  • Eine GUI zur Bankweltfrom tkinter import * 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 fr 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()) ...Aufgabe: Der folgende Quelltextauszug zeigt eine andere Implementierung der grafischen Benutzeroberflche. Hier wird ein zustzliches Objekt benutzt, um smtliche GUI-Objekte zu verwalten. Analysiere das Programm.

  • 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 Objekt- und Klassendiagramm.

  • Zwei-Komponenten-Architektur#----------------------------------# Datenmodellobjekte#----------------------------------

    from bank import *bank = Bank()bank.initBank()

    #----------------------------------# GUI-Objekte#----------------------------------

    from guibank import *guibank = GUIBank(bank)Das bisher entwickelte System zur Verwaltung von Bankkonten hat eine Zwei-Komponenten-Architektur. Die eine Komponente wird vom Datenmodell gebildet. Diese Komponente ist so konzipiert, dass sie ohne eine grafische Benutzeroberflche benutzt werden kann. Die andere Komponente umfasst alle Klassen, die fr die Erzeugung und Verwaltung der grafischen Benutzeroberflche bentigt werden. Da Objekte dieser Klassen u. a. fr die Darstellung des Datenmodells zustndig sind, drfen sie Zugriff auf Datenmodell-Objekte haben.

  • Trennung Datenmodell - GUIDie Trennung zwischen Datenmodell und GUI ist ein Prinzip bei der Entwicklung von Systemen mit grafischer Benutzeroberflche, das hilft, klar strukturierte und gut wartbare Programme zu erstellen: Whrend GUI-Objekte auf Objekte des Datenmodells zugreifen drfen, ist der umgekehrte Zugriff nicht erlaubt.

  • Model - View - ControlBisher war das GUI-Objekt sowohl fr die Prsentation der Daten auf der Benutzerober-flche, als auch fr die Ereignisverarbeitung zustndig. Diese beiden Zustndigkeiten sollen jetzt aufgeteilt werden: Einerseits soll es Prsentations-objekte geben, die nur fr die Darstellung der Daten zustndig sind, andererseits Steuerungs-objekte, die die Verbindungen zwischen Prsentationsobjekten und Datenmodellobjekten herstellen und die Ereignisverarbeitung festlegen. Diese weitere Aufteilung der Zustndigkeiten soll sptere nderungen oder Erweiterungen des Softwaresystems erleichtern und eine Wiederverwendbarkeit einzelnen Komponenten ermglichen. ModelViewControl

  • Model - View - ControlModelclass 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 - View - ControlViewfrom 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

  • Model - View - ControlControlfrom model_bank import *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()

  • Model - View - ControlAufgabe eines GUIBank-Objekts ist es, die grafische Benutzeroberflche zu erzeugen.ModelViewControlAufgabe eines Controler-Objekts ist es, die Datenmodell- und GUI-Objekte zu erzeugen und zu verknpfen.Aufgabe eines Model-Objekts ist es, einen Aspekt der Miniwelt abzubilden..Beachte, dass ein Controler-Objekt Zugriff auf Model- und View-Objekte hat.

  • Callback-Funktionclass 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) ...Parameter fr eine Callback-FunktionEine Callback-Funktion (bzw. Rckruffunktion) ist eine Funktion, die einer anderen Funktion als Parameter bergeben wird und von dieser unter gewissen Bedingungen aufgerufen wird.

  • Callback-Funktionclass 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: ...Callback-FunktionEine Callback-Funktion (bzw. Rckruffunktion) ist eine Funktion, die einer anderen Funktion als Parameter bergeben wird und von dieser unter gewissen Bedingungen aufgerufen wird.Callback-Funktion

  • Strategie: Befragenclass 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: ...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 Schaltflche) und besorgt sich die genderten Daten zur Anzeige auf dem vorgesehenen Label. 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): # Verarbeitung der Daten self.uhr.tick() # Anzeige der Daten uhrzeit = str(self.uhr.stunden) + ":" + \ str(self.uhr.minuten) + ":" + \ str(self.uhr.sekunden) self.labelUhr.config(text=uhrzeit)Befragennderung# Datenmodellfrom uhr import *uhr = Uhr()# GUI-Objektfrom guiuhr import *guiuhr = GUIUhr(uhr)guiuhr.fenster.mainloop()

  • Strategie: Beobachtenimport 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 stellen(self, h, m, s): self.stunden.setzen(h) self.minuten.setzen(m) self.sekunden.setzen(s) self.beobachter.anzeigeAktualisieren()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 verndert hat.... 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()

    def ticken(self): self.aktiv = True self.timer = Timer(1, self.tick) self.timer.start()Beobachter benachrichtigennderung

  • Strategie: Beobachtenfrom 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()

    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)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. # Datenmodellfrom uhr import *uhr = Uhr()# GUI-Objektfrom guiuhr import *guiuhr = GUIUhr(uhr)# Beobachter festlegenuhr.setBeobachter(guiuhr)# Ereignisschleife startenguiuhr.fenster.mainloop()

  • bungenAufgabe 1 (siehe www.inf-schule.de 1.12.7.8)Die Klasse ModuloZaehler beschreibe Zhler, die modulo einer vorgegebenen Zahl zhlen. Entwickle eine einfache grafische Benutzeroberflche, mit der man das Verhalten eines Modulo-Zhlers verdeutlichen kann.

  • bungenAufgabe 2 (siehe www.inf-schule.de 1.12.7.8)Ziel ist es, ein objektorientieres Datenmodell mit einer grafische Benutzeroberflche zu verknpfen. Als Miniwelt betrachten wir das Spiel chuck a luck.

  • bungenAufgabe 2 (siehe www.inf-schule.de 1.12.7.8)Fr die Benutzeroberflche kannst du eine bereits entwickelte Implementierung bernehmen. Implementiere das gesamte Programm so, dass eine klare Trennung zwischen Datenmodell und GUI erkennbar ist.

  • Teil 6Vererbung

  • SparkontoEin 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?

  • SparkontoEin Sparkonto kann als spezielles Konto angesehen werden, das - im Vergleich zu einem herkmmlichen Konto - nur in einigen Bestandteilen abgendert worden ist.Aufgabe:Wie wrde man ein solches Klassendiagramm wohl lesen?

  • SparkontoAufgabe:Analysiere die Implementierung der Klasse Sparkonto. Alles klar?Teste auch diese Implementierung.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 mglich!")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.minimum: self.stand = self.stand - betrag else: print("Auszahlung nicht mglich!") else: print("Auszahlung nicht mglich!")

    def zinsenGutschreiben(self): zinsen = self.stand * (self.zinssatz / 100) self.einzahlen(zinsen)

  • VererbungVererbung 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.SubklasseBasisklasse / Superklassebernehmen, ergnzen 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 zustzliche Attribute und Methoden ergnzen.

  • Implementierung in Pythonclass 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 mglich!")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.minimum: self.stand = self.stand - betrag else: print("Auszahlung nicht mglich!") else: print("Auszahlung nicht mglich!")

    def zinsenGutschreiben(self): zinsen = self.stand * (self.zinssatz / 100) self.einzahlen(zinsen)VererbungberschreibenErgnzenbernehmen

  • bungenAufgabe (siehe www.inf-schule.de 1.12.7.1 und 1.12.8.5)Auf den folgenden Folien werden verschiedene Implementierungen einer grafischen Benutzeroberflche gezeigt.Analysiere und erklre, was in den jeweiligen Version unterschiedlich implementiert wird.

  • bungen# Datenmodellfrom wuerfel import *wuerfel = Wuerfel()# GUIfrom tkinter import *# Ereignisverarbeitungdef Wuerfel_Click(): # Verarbeitung der Daten wuerfel.werfen() # Anzeige der Daten labelWuerfel.config(text=str(wuerfel.augen))# Erzeugung des Fenstersfenster = Tk()fenster.title("Wrfel")fenster.geometry('120x110')# Eingabefeld fr die ZahllabelWuerfel = Label(master=fenster, text="1", background="#FBD975")labelWuerfel.place(x=45, y=40, width=30, height=30)# Button zum AuswertenbuttonWuerfel = Button(master=fenster, text="Wrfel werfen", command=Wuerfel_Click)buttonWuerfel.place(x=10, y=80, width=100, height=20)# Aktivierung des Fenstersfenster.mainloop()from random import randint

    class Wuerfel(object): def __init__(self): self.augen = 1

    def werfen(self): self.augen = randint(1, 6)

  • bungenfrom tkinter import *

    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 fr 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="Wrfel 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))# Datenmodellfrom wuerfel import *wuerfel = Wuerfel()# GUI-Objektfrom guiwuerfel import *guiwuerfel = GUIWuerfel(wuerfel)guiwuerfel.fenster.mainloop()

  • bungenfrom tkinter import *

    class GUIWuerfel(Tk): def __init__(self, wuerfel): # Referenzattribute zum Datenmodell Tk.__init__(self) self.wuerfel = wuerfel # Erzeugung des Fensters self.title("Wrfel") self.geometry('120x110') # Eingabefeld fr 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="Wrfel 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))# Datenmodellfrom wuerfel import *wuerfel = Wuerfel()# GUI-Objektfrom guiwuerfel import *guiwuerfel = GUIWuerfel(wuerfel)guiwuerfel.mainloop()

  • LiteraturhinweiseEs gibt eine Vielzahl von fachwissenschaftlichen Darstellungen zur objektorientierten Modellierung und Programmierung. Hier wurden folgende Lehrwerke benutzt: - D. J. Barnes, M. Klling: 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 Schulbcher, die systematisch in die objektorientierte Programmierung einfhren, z. B.: - Siegfried Spolwig: Objektorientierung im Informatikunterricht. Dmmler-Verlag 1997. - P. Damann, J. Wemen: Objektorientierte Programmierung mit Delphi, Band 2. Klett-Verlag 2003.Viele interessante Artikel mit Unterrichtsvorschlgen bzw. fachdidaktischen Auseinandersetzungen findet man in der Zeitschrift LOG IN. Das Themenheft 128/129 ist speziell dem Thema Objektorientiertes Modellieren und Programmieren gewidmet. ...

  • LiteraturhinweiseIm 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