Kapitel 14: Einführung in die Objekt-Orientierte Programmierung Einführung in die Informatik Wintersemester 2007/08 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 Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 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 Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg Objektorientierte Sichtweise: Welt als System von Objekten, die untereinander Botschaften austauschen Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 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) Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg Prof. B. Jung 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 z.B. Mark und Sascha sind Instanzen von Blumenhändler Alle Instanzen einer Klasse Prof. B. Jung beherrschen dieselben Methoden haben dieselben Attribute (wenn auch mit verschiedenen Werten) Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 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] Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg >>> 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. Jungcmp(x, y) -> -1, 0, Einführung 1 TU Bergakademie Freiberg in die Informatik, WS 2007/08 4 OOP in Python: Arbeiten mit vordefinierten Klassen Beispiel: Erzeugen grafischer Benutzeroberflächen mit dem Modul "Tkinter" 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() Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 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 Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 5 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 TU Bergakademie Freiberg Einführung in die Informatik, WS 2007/08 >>> 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) Einführung in die Informatik, WS 2007/08 Prof.return B. Jung TU Bergakademie Freiberg 6 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 OOPSprachen) nicht erzwungen. Es werden aber Möglichkeiten bereit gestellt, Attribute nach außen zu verstecken Æ Sichtbarkeit von Attributen (und Methoden) Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 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 Prof. B. Jung Zugriff von außerhalb des Moduls (Phython-Skripts) eingeschränkt syntaktisch: Attributname beginnt mit einem Unterstrich, z.B. _x Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 7 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 >>> TU Bergakademie Freiberg Einführung in die Informatik, WS 2007/08 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, total number of circles = >>> c2 = Circle4(0.0, 0.0, total number of circles = >>> c3 = Circle4(3.0, 3.0, total number of circles = Einführung in die Informatik, WS 2007/08 >>> 1) 1 2) 2 3) 3 TU Bergakademie Freiberg 8 Konzepte der OOP - Vererbung Oberklassen und Unterklassen in der Biologie Quelle: de.wikipedia.org Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 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 Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 9 OOP in Python - Vererbung Definition von Oberklassen class Klassenname(Oberklasse1, Oberklasse2 , …): … class GeomFig: def __init__(self, x, y): self.x = x self.y = y Circle hat Oberklasse GeomFig 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 >>> Aufruf des Konstruktors der Oberklasse Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 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 Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 10 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 Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 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) in Python ist dies nicht möglich, aber vielen anderen OOP-Sprachen auch in Python wichtiges Programmiermittel 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 Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 11 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' Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 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) Einführung in die Informatik, WS 2007/08 'x=5.0 y=8.0 r=1.0' TU Bergakademie Freiberg 12 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 >>> james = Mitarbeiter("007", "Bond", 35) >>> print james.personalnr 007 >>> print james.name Bond >>> print james.alter 35 TU Bergakademie Freiberg Einführung in die Informatik, WS 2007/08 Prof. B. Jung 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 Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 13 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 darin Initialisierung der Objektattribute Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 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 Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg 14