Termin 10: Einführung in die ObjektOrientierte Programmierung Grundlagen der Informatik Wintersemester 2006/07 Prof. Bernhard Jung Übersicht Grundzüge der Objektorientierten Programmierung (OOP) am Beispiel von Python Einleitung Verwendung vordefinierter Objekte in Python Definition eigener Klassen in Python Attribute und Methoden Klassenattribute Vererbung Polymorphismus Hauptlernziele • Verständnis allgemeiner Prinzipen der OOP • Fähigkeit, einfache objektorientierte Programme in Python schreiben können Literatur Michael Weigend. Objektorientierte Programmierung mit Python. 2. Aufl. Bonn (MITP) 2005. Bernd Oestereich. Objektorientierte Softwareentwicklung. Oldenbourg. 1999 Prof. B. Jung Grundlagen der Informatik, WS 2006/07 1 Was sind Objekte? Reale Objekte z.B. Auto, Telefon, Mensch, Konto, Versicherungspolice, … Software-Objekte Modellieren Ausschnitte der Realität Sachgerechte Abstraktion bzgl. Eigenschaften / Attributen Methoden / Verhalten / Operationen / Algorithmen Prof. B. Jung Grundlagen der Informatik, WS 2006/07 Objektorientierte Sichtweise: Welt als System von Objekten, die untereinander Botschaften austauschen Prof. B. Jung Grundlagen der Informatik, WS 2006/07 2 Objekte besitzen Attribute und beherrschen Methoden Name: Sascha Stadt: Berlin Öffnungszeiten: Mo bis Fr 10:00-18:30 Attribute (Daten) Blumensträuße binden Lieferauftrag entgegen nehmen Boten schicken Methoden (Algorithmen) Prof. B. Jung Grundlagen der Informatik, WS 2006/07 Konzepte der OOP: Klassen und Objekte Klasse = Bauplan / Schema für Objekte beschreibt prinzipiellen Aufbau (Eigenschaften/Attribute) und Verhalten bei Erhalt von Nachrichten (verfügbare Methoden) einer Menge von gleichartigen Objekten Klassen verschmelzen logisch zusammengehörige Daten und Operationen zu einer Einheit Instanz (Objekt) = Konkretisierung / Inkarnation einer Klasse Alle Instanzen einer Klasse Prof. B. Jung z.B. Mark und Sascha sind Instanzen von Blumenhändler beherrschen dieselben Methoden haben dieselben Attribute (wenn auch mit verschiedenen Werten) Grundlagen der Informatik, WS 2006/07 3 OOP in Python: Arbeiten mit vordefinierten Klassen Aufruf von Methoden eines Objekts mit Syntax: objekt.methode() Methoden für Listen-Objekte list.reverse() – Reihenfolge der Listenelemente wird umgekehrt list.sort() – Sortierung der Listenelemente in aufsteigender Reihenfolge list.extend(list2) – Liste wird um Elemente von list2 erweitert … >>> >>> >>> [1, >>> >>> [6, >>> >>> [1, Prof. B. Jung l = [1,3,5,2] l.extend([7,6]) print l 3, 5, 2, 7, 6] l.reverse() print l 7, 2, 5, 3, 1] l.sort() print l 2, 3, 5, 6, 7] Grundlagen der Informatik, WS 2006/07 >>> help(list) Help on class list in module __builtin__: class list(object) | list() -> new list | list(sequence) -> new list initialized from sequence's items | | Methods defined here: … | append(...) | L.append(object) -- append object to end | | count(...) | L.count(value) -> integer -- return number of occurrences of value | | extend(...) | L.extend(iterable) -- extend list by appending elements from the iterable | | index(...) | L.index(value, [start, [stop]]) -> integer -- return first index of value | | insert(...) | L.insert(index, object) -- insert object before index | | pop(...) | L.pop([index]) -> item -- remove and return item at index (default last) | | remove(...) | L.remove(value) -- remove first occurrence of value | | reverse(...) | L.reverse() -- reverse *IN PLACE* | | sort(...) | L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*; |Prof. B. Jung cmp(x, y) -> -1, 0,Grundlagen 1 der Informatik, WS 2006/07 4 OOP in Python: Arbeiten mit vordefinierten Klassen Beispiel: Erzeugen grafischer Benutzeroberflächen mit dem Modul "Tkinter" (verfügbar nur in IDLE; nicht Jython/JES) Klasse Tk repräsentiert ein Fenster Attribute, u.a. Methoden, u.a. label title(String) mainloop() Erzeugen von Tk-Objekten per Konstruktor: Tk() Klasse Label repräsentiert einfaches Text-Element Methoden, u.a. Erzeugen von Label-Objekten per Konstruktor: Label( Tk, …) Prof. B. Jung pack() Grundlagen der Informatik, WS 2006/07 OOP in Python: Arbeiten mit vordefinierten Klassen from Tkinter import * fenster = Tk() fenster.title("Hello World") fenster.label = Label(fenster, text="Hello Tkinter World") fenster.label.pack() fenster.mainloop() Prof. B. Jung Grundlagen der Informatik, WS 2006/07 5 Innovation Time "Person of the Year 2006" Internetnutzer "Yes, you. You control the Information Age. Welcome to your world." "creators and consumers of user-generated content are transforming art and politics and commerce" Web 2.0: Bereitgestellung von Medieninhalte durch normale Internetnutzer z.B. blogs, youtube, flickr, myspace, … www.time.com Prof. B. Jung Grundlagen der Informatik, WS 2006/07 OOP in Python: Definition eigener Klassen (1) Definition von Klassen mit Schlüsselwort class in besonderer Methode __init__ werden Attribute der Klasse initialisiert Konstruktor der Klasse, die bei Erzeugung von Instanzen aufgerufen wird besondere Variable self referenziert das neue Objekt Methode __init__ sollte immer als erstes Argument self haben Instanzen werden durch Aufruf der Klasse erzeugt Argumente entsprechend Konstruktor, jedoch ohne erstes Argument Beispiel: Objekte vom Typ "Kreis" beschrieben über Position (x,y) und Radius class Circle1: >>> c = Circle1() Erzeugen einer Instanz >>> print c def __init__(self): <__main__.Circle1 instance at 0x00B45850> self.x = 0.0 >>> print c.x self.y = 0.0 0.0 self.r = 1.0 >>> c.x = 2.0 >>> print c.x 2.0 >>> c.x, c.y = 1.5, 2.5 >>> print c.x, c.y 1.5 2.5 Prof. B. Jung Grundlagen der Informatik, WS 2006/07 >>> 6 OOP in Python: Definition eigener Klassen (2) Konstruktor mit mehreren Argumenten Bem: das Überladen von Methoden (z.B.: __init__ ) in derselben Klassendefinition - d.h. gleicher Methodenname, aber unterschiedliche Argumente – ist in Python i.Ggs. zu anderen OOP-Sprachen nicht möglich stattdessen: Methoden mit Default-Argumenten Definitionen der Methoden getPos(), setPos() in Definition mit Argument self bei Aufruf der Methode ohne Argument self class Circle2: def __init__(self,x=0.0,y=0.0,r=1.0): self.x = x self.y = y self.r = r def setPos(self, x, y): self.x, self.y = x, y >>> c = Circle2(2.0, 1.0, 1) >>> c.getPos() (2.0, 1.0) >>> c.setPos(-1.0, 3) >>> c.getPos() (-1.0, 3) >>> c.r 1 def getPos(self): (self.x, self.y) Grundlagen der Informatik, WS 2006/07 Prof.return B. Jung Konzepte der OOP: Geheimnisprinzip (Information Hiding) Geheimnisprinzip (Information Hiding) Auf die Attribute eines Objekts kann nicht direkt zugegriffen werden, stattdessen erfolgt der Zugriff ausschließlich über Zugriffsoperatoren. Es werden also die Implementierungen der Operationen und die Datenstrukturen selbst versteckt. Vorteil: Implementierungsdetails können beliebig geändert werden, ohne Auswirkung auf den Rest des Programms zu haben Bem: das Geheimnisprinzip wird in Python (wie auch in anderen OOP-Sprachen) nicht erzwungen. Es werden aber Möglichkeiten bereit gestellt, Attribute nach außen zu verstecken Æ Sichtbarkeit von Attributen (und Methoden) Prof. B. Jung Grundlagen der Informatik, WS 2006/07 7 OOP in Python: Sichtbarkeit von Attributen Zugriff auf Attribute kann eingeschränkt werden Öffentliche Attribute: lesender und schreibender Zugriff auch außerhalb der Klassendefinition z.B. Klasse Circle2 >>> c = Circle2(2.0, 10.0, 3.5) >>> print c.x, c.y, c.r 2.0 10.0 3.5 Private Attribute in Python Unterscheidung zwischen stark und schwach privaten Attributen stark private Attribute Zugriff von außen überhaupt nicht möglich syntaktisch: Attributname beginnt mit zwei Unterstrichen, z.B. __x schwach private Attribute Zugriff von außerhalb des Moduls (Phython-Skripts) eingeschränkt syntaktisch: Attributname beginnt mit einem Unterstrich, z.B. _x Prof. B. Jung Grundlagen der Informatik, WS 2006/07 OOP in Python: Sichtbarkeit von Attributen Beispiel Klasse Circle3 mit (stark) privaten Attributen Zugriff auf Objekt-Attribute nur über getter- und setter-Methoden class Circle3: def __init__(self, x, y, r): self.__x = x self.__y = y self.__r = r def setX(self, x ): self.__x = x def getX(self): return self.__x def setRadius(self, r): self.__r = r def getRadius(self): return self.__r Prof. B. Jung >>> c = Circle3(2.0, 10.0, 3.5) >>> print c.__x Traceback (most recent call last): File "<pyshell#40>", line 1, in toplevelprint c.__x AttributeError: Circle3 instance has no attribute '__x' >>> print c.getX() 2.0 >>> Grundlagen der Informatik, WS 2006/07 8 OOP in Python: Klassenattribute Beispiel: Es soll ein Zähler __numCircles für die Anzahl der Instanzen einer Klasse Circle4 erstellt werden keine Eigenschaft einzelner Instanzen gehört logisch zur Klasse Circle4 Initialisierung außerhalb von __init__ Æ Klassenattribut class Circle4: __numCircles = 0 # Klassenattribut def __init__(self, x, y, r): Zugriff mit Klassenname.Attributname self.__x = x self.__y = y self.__r = r Circle4.__numCircles = Circle4.__numCircles + 1 print "total number of circles = ", Circle4.__numCircles Prof. B. Jung >>> c1 = Circle4(1.0, 1.0, 1) total number of circles = 1 >>> c2 = Circle4(0.0, 0.0, 2) total number of circles = 2 >>> c3 = Circle4(3.0, 3.0, 3) total number of circles = 3 Grundlagen der Informatik, WS 2006/07 >>> Konzepte der OOP - Vererbung Oberklassen und Unterklassen in der Biologie Quelle: de.wikipedia.org Prof. B. Jung Grundlagen der Informatik, WS 2006/07 9 Konzepte der OOP - Vererbung Vererbung der Attribute (und Methoden) der Oberklasse an Unterklasse d.h. alle geometrischen Figuren haben Position x, y Kreis hat neben Position zusätzlich Radius Rechteck hat neben Position zusätzlich Seitenlängen a, b … Geometrische Figur Attribute: x, y Kreis Rechteck Dreieck Attribute: radius Attribute: a, b Attribute: a, b, c Prof. B. Jung Grundlagen der Informatik, WS 2006/07 OOP in Python - Vererbung Definition von Oberklassen class Klassenname(Oberklasse1, Oberklasse2 , …): … class GeomFig: def __init__(self, x, y): self.x = x self.y = y class Circle(GeomFig): def __init__(self, x, y, r): GeomFig.__init__(self, x, y) self.r = r Prof. B. Jung >>> c = Circle(1, 2, 4) >>> print c.x, c.y, c.r 1 2 4 >>> Circle hat Oberklasse GeomFig Aufruf des Konstruktors der Oberklasse Grundlagen der Informatik, WS 2006/07 10 OOP in Python – Vererbung Feinheiten I.a. Vererbung von Attributen und Methoden an Unterklasse Unterklassen können Methoden der Oberklasse überschreiben Unterklasse definiert namensgleiche Methode wie Oberklasse ("method overriding") oft sinnvoll Æ Polymorphismus … Unterklassen können Attribute der Oberklasse überschreiben stark private Attribute werden nicht vererbt Unterklasse definiert namensgleiches Attribut wie Oberklasse ("shadowing") meistens nicht sinnvoll In Python ist auch Mehrfachvererbung möglich (d.h. mehr als eine Oberklasse) Mehrfachvererbung ist z.T. problematisch (z.B. in Java daher nicht möglich) Prof. B. Jung Grundlagen der Informatik, WS 2006/07 Konzepte der OOP – Mehrfachvererbung Nixon-Raute (Nixon diamond) … Quäker def istPazifist(): return True Republikaner def istPazifist(): return False Spezialisierung-von Spezialisierung-von Nixon Problem: welche Methoden-Definition soll bei Objekten vom Typ Nixon gelten? Æ in Python würde Methode der in der Klassendefinition zuerst genannten Oberklasse angewendet Prof. B. Jung Grundlagen der Informatik, WS 2006/07 11 Konzepte der OOP - Polymorphismus Polymorphismus ("Vielgestaltigkeit") : in verschiedenen Klassen können Methoden gleichen Namens definiert werden auch: gleichnamige Methoden in Ober- und Unterklasse (method overriding) damit verhalten sich die Instanzen der verschiedenen Klassen sehr unterschiedlich bei Erhalt derselben Botschaft (d.h. Aufruf jeweils unterschiedlicher Funktionen) Beispiel Definition einer Methode drucke() in Oberklasse und in Unterklasse … Prof. B. Jung Grundlagen der Informatik, WS 2006/07 OOP in Python – Polymorphismus / Method Overriding class GeomFig: # Oberklasse def __init__(self, x, y): self._x = x self._y = y def drucke(self): return "x=" + str(self._x) + " y=" + str(self._y) class Circle(GeomFig): # Unterklasse def __init__(self, x, y, r): GeomFig.__init__(self, x, y) überschreibende Methode self._r = r def drucke(self): return "x="+str(self._x) +" y="+ str(self._y) + " r="+str(self._r) Prof. B. Jung >>> g = GeomFig(0,0) >>> g.drucke() 'x=0 y=0' >>> c = Circle(1.0, 1.0, 2) >>> c.drucke() 'x=1.0 y=1.0 r=2' Grundlagen der Informatik, WS 2006/07 12 OOP in Python – Polymorphismus die Methode __str__ besondere Methode __str__ liefert eine String-Repräsentation eines Objekts zurück wird von print und str() verwendet (vordefiniert in impliziter Oberklasse object aller Python-Objekte) class Circle(GeomFig): def __init__(self, x=0.0, y=0.0, r=0.0): GeomFig.__init__(self, x, y) besondere Methode __str__ self._r = r def __str__(self): return "x="+str(self._x) + " y="+str(self._y) + " r="+str(self._r) >>> o = object() >>> o.__str__() '<object object at 0x0099C438>' >>> print o # benutzt __str__ <object object at 0x0099C438> Prof. B. Jung >>> c = Circle(5.0, 8.0, 1.0) >>> c.__str__() 'x=5.0 y=8.0 r=1.0' >>> print c # benutzt __str__ x=5.0 y=8.0 r=1.0 >>> str(c) Grundlagen der Informatik, WS 2006/07 'x=5.0 y=8.0 r=1.0' Sonstiges Python-Klassen können auch ohne Methoden und ohne Sichtbarkeitsmodifikatoren der Attribute (d.h. alle Attribute öffentlich) definiert werden d.h. Definition von Klassen ohne OOP-Prinzipien wie Geheimnisprinzip Entsprechung in etwa zu 'Strukturen' in C oder 'Records' in Pascal class Mitarbeiter: def __init__(self, persnr, name, alter): self.personalnr = persnr self.name = name self.alter = alter Prof. B. Jung >>> james = Mitarbeiter("007", "Bond", 39) >>> print james.personalnr 007 >>> print james.name Bond >>> print james.alter 39 Grundlagen der Informatik, WS 2006/07 13 Sonstiges Python-Klassen können auch ganz ohne Methoden und Attribute definiert werden Æ "leere Klasse" Hinzufügen von Attributen für Instanzen ist möglich dies gilt für auch für Instanzen beliebiger Klassen Dadurch auch Fehleranfälligkeit, z.B. Schreibfehler in Attributnamen Verringerte Fehleranfälligkeit durch strikte Einhaltung des Geheimnisprinzips, d.h. kein direkter Zugriff von außen auf Attribute, sondern nur auf Klassen class Employee: pass leere Anweisung ("tue nichts!") >>> john = Employee() # Erzeuge einen leeren Mitarbeiter-Satz. # Fuelle die Felder des Satzes. john.name = 'John Doe' john.dept = 'computer lab' john.salary = 1000 Prof. B. Jung Grundlagen der Informatik, WS 2006/07 Zusammenfassung: Definition eigener Klassen in Python Klassendefinition: Klassenkopf + Klassenrumpf Klassenkopf Schlüsselwort class Name der Klasse evtl. Oberklassen in runden Klammern Doppelpunkt Klassenrumpf (eingerückt) Definition der Klassenattribute Definition der __init__-Methode (Konstruktor) Definition weiterer Methoden Prof. B. Jung darin Initialisierung der Objektattribute Grundlagen der Informatik, WS 2006/07 14 Zusammenfassung: Konzepte der OOP Objektorientierung = Klassen und Objekte + Kommunikation mit Nachrichten + Vererbung (Coad & Yourdon) Objektorientierte Programmiersprachen Java, C++, C, Object Pascal (Delphi), Smalltalk, … Python: strikt objektorientiert – alle Daten sind Objekte Prof. B. Jung Grundlagen der Informatik, WS 2006/07 15