. . . steht für objektorientiertes Programmieren und war/ist die Revolution (!) in der Software-Erstellung der letzten 20 Jahre! Unser Objekt ist beispielsweise eine Schildkröte, und eine Schildkröte hat bestimmte Eigenschaften (welche?). Damit nicht genug: eine Schildkröte kann bestimmte Aktionen ausführen (welche?). Man packt beides -Eigenschaften & Aktionen- zusammen in einer Vereinbarung, die man sich als Schablone vorstellen kann: alle Schildkröten werden nach diesem Muster "konstruiert", beim Menschen entspricht diesem Bauplan so in etwa die DNS (?!?). Die Vereinbarung der Schildkröte nennt man "Klasse" und unsere Aufgabe ist es, sinnvolle (!) Klassen zu programmieren. Wenn wir dagegen eine richtige Schildkröte benutzen, so ist das ein konkretes (Schildkröten-)Objekt. Beachte: zeichnen kann nur dieses Objekt (warum?), in der Klasse steht nur wie's geht (die Vereinbarung).
Für die Klassen gibt es eine grafische Notation (UML), mit der man kurz & knapp die Eigenschaften & Methoden darstellen kann (denke an Struktogramme).
Bleibt mir nur noch folgender Hinweis: Oops ist grundlegend wegen der sogenannten Vererbung. Das kann man durchaus wörtlich nehmen: wenn sich bestimmte Klassen bewährt haben (Fenster!), so erfindet man das Rad nicht mehr neu, sondern vererbt einfach bestimmte Eigenschaften & Methoden an eine Unterklasse und passt da & dort etwas an, fertig!
Worin könnte der Vorteil dieser Vorgehensweise liegen?
________________________________________________________________
________________________________________________________________
Schildkröte heißt auf Englisch turtle, und wenn wir in Python die Schildkröte benutzen wollen, so müssen wir die Bibliothek erst mal importieren. Hier ein Beispiel:
import turtle def dreieck(): turtle.forward(90) turtle.left(120) turtle.forward(90) turtle.left(120) turtle.forward(90) turtle.left(120) ## ausprobieren turtle.reset() dreieck()
Wirkung:
Hier eine kleine Liste von Schildkröten-Befehlen (unvollständig!):
strecke
vorwärtsstrecke
rückwärtswinkel
nach links (gegen den Uhrzeigersinn)winkel
nach rechts (im Uhrzeigersinn)turtle.color('red')
, beachte die beiden Anführungszeichen ' vor und nach 'red
' !)Das Bankkonto ist ein alter Bekannter aus Java-Zeiten, hier die Python-Version:
class Bank: """Einfache Bank-Konto-Klasse""" def __init__(self,kontostand): """Konstruktor: erzeugt Bankkonto""" self.kontostand = kontostand def einzahlung(self, betrag): self.kontostand = self.kontostand + betrag def auszahlung(self, betrag): self.kontostand = self.kontostand - betrag def anzeigen(self): print u"Kontostand: %.2f \u20ac" % self.kontostand # \u20ac = EUR if __name__ == "__main__": # ausprobieren konto = Bank(100) # Bank-Konto erzeugen konto.anzeigen() # und Konto-Stand anzeigen
Zur Erklärung: Eine Klassenvereinbarung beginnt in Python mit dem Schlüsselwort class
gefolgt vom Namen der Klasse. Da die Klassenvereinbarung auch (nur) eine Anweisung ist, folgt nach dem Namen der Doppelpunkt, und ab da wird eingerückt!
Der Konstruktor ist diejenige Methode, die beim Aufruf ein Objekt unserer Bank-Klasse zurückgibt. In der Python-Klassenvereinbarung hat der Konstruktor den treffenden Namen
__init__
. Diese Methode wird also an folgender Stelle aufgerufen:
konto = Bank(100)
Dem Objekt wird beim Aufruf ein Parameter übergeben: der kontostand
. Der erste Parameter self
hat eine besondere Bedeutung: wir können ja mehrere Objekte unserer Bank-Klasse ins Leben rufen, aber woher weiß Python, welche Eigenschaften zu welchem Objekt gehören und welche Methode auf welches Objekt angewendet werden soll? Nun, der Parameter, der jeder Methode in einer Klasse als erstes übergeben wird, ist gerade unser Objekt (self
, in Java: this
). Die Eigenschaft unserer Klasse ist der Kontostand:
self.kontostand
Über das self
ist gewährleistet, dass sich mehrere Konten nicht gegenseitig "ins Gehege" kommen. Und dann war da noch die Vererbung:
class Taschengeld(Bank): """Taschengeld-Konto: man darf nicht ueberziehen . . .""" def __init__(self,kontostand): """Konstruktor: erzeugt Taschengeldkonto""" Bank.__init__(self,kontostand) . . .
In Klammern steht die (Super-)Klasse, von der die Taschengeld-Klasse erbt, und der Konstruktor ruft die Konstruktor-Methode der Super-Klasse auf:
Bank.__init__(self,kontostand)
. In der Taschengeld-Klasse wird die Methode
auszahlung
der Super-Klasse überschrieben, d. h.: wir schreiben in der Unter-Klasse eine Methode (=Funktion) mit gleichem Namen, so dass beim Aufruf dieser Methode nicht die Methode auszahlung
der Super-Klasse aufgerufen wird, sondern die der Taschengeld-Klasse. Damit kann man das Verhalten von Objekten an die jeweilige Situation anpassen.
findest du auf dem Web-Server "muenchen":
http://192.168.0.33
unter lokal => Informatik
dreieck.py
dreieck_sinus.py
bank.py
dir(turtle)
auszahlung
. Schreibe sie erst mal nach dem Muster in der Bank-Klasse und ändere sie dann geeignet ab!bank.py
.