|
[ Home
] [ Seitenende ] [ Teil 1 ] [ Teil 2a ] [ Teil 3 ] [ Teil 4 ] |
|
||||
|
Roboter-Auto „Joy-Car“ - Teil 2b Einführung in die Objekt
orientierte Programmierung (OOP) Die „NeoPixel“-LEDs des „Joy-Car“-Roboters lassen sich alle
mittels sogenannter Methoden wie z.B. der
nachfolgenden ·
Methode <create(DigitalPin.P0, 8, NeoPixelMode.RGB)> programmieren. Dabei spricht man von einer Methode, wenn z.B. die Funktion <create(DigitalPin.P0, 8, NeoPixelMode.RGB)> der Klasse
<neopixel> zugeordnet ist, sich
also die Funktion innerhalb
einer Klasse befindet. Eine Klasse
mit ihren Methoden wiederum lässt sich
zu einem Objekt instanziieren, d.h.
zusammenfassen und z.B. der Instanzvariablen
<strip> wie folgt zuweisen: ·
<strip = neopixel.create(DigitalPin.P0, 8, NeoPixelMode.RGB)> Dabei verfügt ein Objekt, wie z.B. das Objekt <strip> über Attribute (= Eigenschaften) und Methoden (= Vorgehensweisen): (Zum Vergrößern bitte
auf das Bild klicken!) Ein Objekt
wie z.B. das Objekt <strip> dient also dazu, eine oder mehrere Klassen wie z.B. die Klasse <neopixel> aufzunehmen und sozusagen
von außen verfügbar zu machen, ohne dass das Hauptprogramm weiß, wie genau sich das Objekt <strip> zusammensetzt, was es
kann usw. Demzufolge kann man sich von außen betrachtet
ein Objekt als eine Art „Black Box“
vorstellen, die bestimmte Eigenschaften
(= Attribute)
hat, über bestimmte Fähigkeiten
(= Methoden)
verfügt und dazu bestimmte Funktionen
verwendet. Dabei bezeichnet man eine Funktion
innerhalb einer Klasse als Methode.
Diesbezüglich kann man sich unter einer Methode
die Lehre, Vorschrift, Vorgehensweise oder Anleitung zum Erreichen einer
Lösung oder eines Zieles vorstellen: (Zum Vergrößern bitte
auf das Bild klicken!) Jetzt hier an dieser Stelle weiter in die Objekt orientierte Programmierung (OOP) am Beispiel der Programmierung
von „NeoPixel“-LEDs einzusteigen, scheint mir nicht sinnvoll und Ziel
führend, da zwei komplexe Sachverhalte zusammentreffen und damit das
Verständnis dieser Dinge unnötig erschweren. Demzufolge ist es besser, wenn man sich
zunächst stufenweise in die OOP einarbeitet. Und zwar
vom Einfachen zum Schwereren, Komplexeren. Nachfolgend geht es um ein Haus der Breite b,
der Höhe h und der Tiefe t, sodass sich mit den entsprechenden Maßen das
umbaute Volumen V wie bei einem Quader
berechnen lässt: V = b * h * t . Da es aber um das Erlernen der OOP geht, beginnen wir mit nur einer Variablen
und zwar der Höhe h des Hauses: (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_46.py“) Als nächstes „berechnen“ wir die Höhe h in der
Methode <berechne_Haushoehe>. Das Besondere an der
Methode ist, dass diese den Ergebniswert
der globalen Variablen <hoehe> mittels des ·
Statements <return(hoehe)> wieder an das aufrufende (Haupt-) Programm
zurückgibt, obwohl dies eigentlich nicht notwendig wäre, da es sich bei der Variablen <hohe> um eine globale Variable
handelt! Wie man aber sieht, erfolgt der Methodenaufruf <berechne_Haushoehe()> nebst der Ergebnisanzeige direkt in der Stringanzeige des 5x5 Matrix LED-Displays: (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_47.py“) Wir verbessern das obenstehende Programm
dahingehend, indem wir auf die globale Variable <hoehe> innerhalb der Methode <berechne_Haushoehe(get_hoehe)> verzichten und
stattdessen den Wert der Höhe = 12 m über den Methodenkopf und der lokalen Variablen <get_hoehe> wie folgt einlesen: (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_48.py“) Wir
erweitern das bisherige Programm, erzeugen die Klasse <Haus> mit zwei lokalen
Variablen innerhalb der Klasse
und übernehmen die ursprüngliche Funktion
<berechne_Haushoehe(get_hoehe)>
ebenfalls in die Klasse <Haus>, sodass diese innerhalb der Klasse <Haus> zur Methode wird: (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_49.py“) Das Interessante an dem obenstehenden Programm
ist, dass die Klasse
<Haus> wider Erwarten nicht
explizit aufgerufen und gestartet werden muss, sondern nach dem Programmstart ohne weiteres
Zutun automatisch ausgeführt und abgearbeitet wird. Demzufolge startet sich
die Methode <berechne_Haushoehe(get_hoehe)> ebenfalls
automatisch, d.h. zusammen mit der Klasse <Haus>. Obwohl die Methode <berechne_Haushoehe(get_hoehe)> innerhalb der Klasse <Haus> gekapselt ist, sodass man nicht so ohne Weiteres auf die Inhalte der lokalen Variablen <get_hoehe> und <ergebnis_1> von außen aus
dem Hauptprogramm heraus zugreifen
kann, kann man trotzdem mit dem Konstrukt
<Haus.ergebnis_2> auf den Inhalt der lokalen
Variablen <ergebnis_2> zugreifen (siehe roter Kasten oben im Bild). Auf
diese Weise ist die Klasse
<Haus> sehr mächtig, lässt
sich mit dieser sehr viel anstellen und bewerkstelligen. Wir steigern die Leistungsfähigkeit der Klasse <Haus>, indem wir diese von außen, d.h. vom Hauptprogramm aus, aufrufen,
ausführen und dabei gleichzeitig noch den Wert 7 der lokalen Variablen <hoehe_2> mit auf den Weg geben (siehe grüner
Kasten)
und quasi in der Funktion <__init__(hoehe_2)> „berechnen“ und in
der Laufschrift des 5x5 Matrix
LED-Displays anzeigen lassen (siehe roter Kasten): (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_50.py“) Fragen wir doch mal die Künstliche Intelligenz
(KI) mit ChatGPT 4.0 der Suchmaschine
„Bing“ von Microsoft danach, wie
das obenstehende Programm funktioniert, was es genau macht: (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_50.hex“) So, jetzt wissen wir, dass sich die (Spezial-)
Funktion <__init__(hoehe_2)>
auf die Klasse <Haus> bezieht und direkt an diese gekoppelt
ist! Dabei
ermöglicht es die <init>-Funktion, dass man der Klasse <Haus> auch einen eingangsseitigen Parameter in Form eines Wertes der lokalen Variablen <hoehe_2> mit auf den Weg geben kann. Ferner wissen wir jetzt,
dass es sich bei dem ·
Statement <Haus(hoehe_2 = 7)> um ein Objekt(!) der Klasse <Haus> handelt!
Aber wie wir gleich sehen werden, gibt es
natürlich einen „Trick“, wie man über eine Art „Variablen-Kopplung“ dennoch auf die lokale
Variablen <hoehe_2> in der <init>-Funktion zugreifen kann (siehe
roter
Kasten):
(Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_51.py“) Als Nächstes wird der Parameter <self> quasi als Kopplungsvariable an die Klasse <Haus> in der gesamten <init>-Funktion eingesetzt. Anhand des abgewinkelten roten Pfeils sieht man jetzt sehr deutlich, dass es
sich bei der <init>-Funktion um den Kopfteil der Klasse <Haus> handelt, damit sich beim Aufruf des Objektes <Haus(7)> auch ein oder mehrere
Parameter zwecks Initialisierung der Klasse <Haus> übergeben lassen! Dabei hat der Kopfteil der Klasse <Haus> den Vorteil, dass sich in der <init>-Funktion auch weiterer Programmkode programmieren lässt: (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_52.py“) Wir erweitern das bisherige Programm mit dem ·
Statement <return(ergebnis_2)>, um das Berechnungsergebnis der Methode <berechne_Haushoehe()> innerhalb der Klasse <Haus> nach außen an die Instanz <h7> des Objektes <Haus()> zu übergeben! Dabei könnte man die Instanz <h7> auch als Objektvariable <h7> der Klasse <Haus> bezeichnen. Aber gerade weil es sich bei der Instanz <h7> um eine Objekt-Instanz handelt, lässt sich
diese nicht mittels der Scrollanzeige nach außen in der Laufschrift des 5x5 Matrix
LED-Displays anzeigen, sondern nur mittels des ·
Konstrukts <h7.ergebnis_2> (siehe
ganz unten im Programmkode): (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_53.py“) Jetzt sind wir schon mittendrin in der professionellen
Objekt orientierten Programmierung
(OOP)
( siehe pinkfarbener Kasten): (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_54.py“) In dem obenstehenden Programm gibt es neben
dem Objekt <h7> bzw. der Instanz <h7> auf die Klasse <Haus> auch noch zwei <def>-Konstrukte, von denen es sich
bei dem einen Konstrukt um eine Funktion und bei dem anderen
um eine Methode handelt.
Diesbezüglich bietet es sich an, die KI von ChatGPT 4.0 der „bing“-Suchmaschine von Microsoft wie
folgt zu befragen: (Zum Vergrößern bitte
auf das Bild klicken!) Jetzt wissen wir, dass es sich bei dem ·
<def>-Kontrukt <__init__()> um eine Funktion und bei dem ·
<def>-Kontrukt
<berechne_Haushoehe()> um eine Methode handelt! Generell
gilt die Regel, dass eine Funktion innerhalb einer Klasse als Methode bezeichnet
wird! Wie wir wissen, unterscheidet man bei der Programmierung zwischen globalen
und lokalen Variablen. Dabei werden Variablen, die innerhalb des Hauptprogramms deklariert und
initialisiert werden als globale Variablen bezeichnet und Variablen, die innerhalb einer Funktion
oder Methode deklariert und
initialisiert werden als lokale Variablen. Während lokale
Variablen innerhalb einer Funktion oder Methode gegenüber
dem Hauptprogramm gekapselt
sind, sodass man von außen aus dem Hauptprogramm nicht auf diese zugreifen kann, lässt sich bei den globale Variablen von überall her auf diese zugreifen. Wir erweitern das Programm „joy-car_teil_02_prog_54.hex“
ein weiteres Mal, indem wir die Methode
<berechne_Haushoehe()>, die bisher für sich
genommen völlig unabhängig von der Klasse
<Haus> war, an genau diese
koppeln. Dabei bezieht sich die Koppelung
an die Klasse <Haus> sowohl auf die jeweilige Methode selbst, als auch auf lokale Variable im Methodenkopf sowie in der Methode selbst.
Während sich beim Programmstart die Funktion
<__init__()> automatisch mit dem Hauptprogramm zusammen startet,
verhält es sich bei Methoden (= Funktionen innerhalb einer Klasse) nicht so,
starten sich diese nicht automatisch zusammen mit dem Hauptprogramm. Vielmehr muss man Methoden sozusagen manuell starten wie z.B. mit dem 1.
Statement <ergebnis_2 = berechne_Haushoehe(hoehe)> Und genau dies funktioniert nach der
Umstellung mit der Koppelung an
die Klasse <Haus> nicht mehr (siehe grüner
Kasten):
(Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_55.py“) In diesem Zusammenhang stellt sich nicht nur
die Frage, was es mit dem <self>-Parameter genau auf sich hat, sondern (Zum Vergrößern bitte
auf das Bild klicken!) auch, wie sich jetzt die Methode <berechne_Haushoehe(self, hoehe)> von außen aus dem Hauptprogramm heraus aufrufen lässt. Diesbezüglich wissen wir ja bereits, wie man
von außen aus dem Hauptprogramm
heraus auf die lokale Variable <ergebnis_2> der Klasse <Haus> zugreift: 2.
Statement <h7.ergebnis_2> Demgemäß bietet es sich an, das vorgenannte Statement in abgewandelter Form auch auf den <Methoden>-Aufruf anzuwenden: 3.
Statement <h7.berechne_Haushoehe(h7.hoehe)> Da die Methode
<berechne_Haushoehe(self, hoehe)> innerhalb der Klasse
<Haus> mittels des 4.
Statements <return self.ergebnis_1> auch einen Ergebniswert <self.ergebnis_1> an das aufrufende Programm zurückliefert, stellt sich
die Frage, wie man die Variable <self.ergebnis_1> nennen soll: (Zum Vergrößern bitte
auf das Bild klicken!) Da die Methode
<berechne_Haushoehe(self, hoehe)> der Klasse <Haus> mit dem 5.
Statement <h7.berechne_Haushoehe(h7.hoehe)> vom Hauptprogramm
aus aufgerufen wird und dabei gleichzeitig einen Ergebniswert an dieses zurückliefert, wählen wir die globale Variable <haus_hoehe> für die Entgegennahme des Ergebniswertes: (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_56.py“) Jetzt wo wir wissen, wie man die Klasse <Haus> mit der Instanzvariablen
<h7> zum Objekt instanziiert, können
wir auch eine andere Instanzvariable
wie z.B. die Instanzvariable <haus_hoehe> dem Objekt der Klasse <Haus> zuordnen: (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_57.py“) Wenn man wissen will, ob und wie das Programm
funktioniert, dann muss man sich die Mühe machen einzelnen Statements im
Hauptprogramm systematisch der Reihe nach abarbeiten bzw. aufrufen. Zu diesem
Zweck empfiehlt es sich immer nur ein Statement aufzurufen und dabei die anderen mittels „#“
auszukommentieren, damit man den Überblick behält. Beginnen wir also mit dem 1.
Statement <h7 : Haus =
Haus(7)> Beim Start des obenstehenden
Programms mit nur diesem einzelnen Statement im Hauptprogramm
wird die Klasse <Haus> aufgerufen und dabei der Wert 7
als (Eingangs-) Parameter zwecks weiterer Berechnung mit übergeben. Dabei
wird die Übernahme bzw. das Einlesen des Parameters
mit dem Wert 7 von der Funktion
<__init__()> bewerkstelligt. Da die nachfolgende Methode <berechne_Haushoehe(self, hoehe)> der Klasse <Haus> an genau diese gekoppelt (= instanziiert) ist, muss die Funktion <__init__()> den eingelesenen Parameter mit dem Wert 7, der in der lokalen Variablen <hoehe_2> gespeichert wurde,
ebenfalls instanziieren. Und zwar mit dem Statement <self.hoehe_2 = hoehe_2>. Dementsprechend bekommt man die Laufschriftanzeigen „1a) " 7“ und „1b) " 7“ im 5x5 Matrix LED-Display angezeigt. Da aber die
nachfolgende Methode <berechne_Haushoehe(self, hoehe)> nicht explizit aufgerufen wird, erfolgt auch
weiter keine Laufschriftanzeige!
Da das 2.
Statement <h7.berechne_Haushoehe(h7.hoehe)> die Instanziierung der
Klasse <Haus> zum Objekt <Haus> mit der Instanzvariablen <h7> voraussetzt bzw. auf
diese aufbaut, bekommt man als erstes die Laufschriftanzeigen „1a) " 7“ und „1b) " 7“ und anschließend „2a) " 6“ und „2b) " 9“ im 5x5 Matrix LED-Display angezeigt. Das 3.
Statement <haus_hoehe : Haus =
Haus(11)>
läuft wieder engl.
„stand-alone“, d.h. eigenständig, ohne das 1. oder 2. Statement
vorauszusetzen, obwohl die neue Instanzvariable
<haus_hoehe> die gleichnamige Klasse <Haus> verwendet, aber jetzt mit dem eingelesenen Parameter und dem Wert 11,
sodass man die Laufschriftanzeigen „1a) " 11“ und „1b) " 11“ im 5x5 Matrix LED-Display angezeigt bekommt! Das 4.
Statement <basic.show_string("3a.) haus_hoehe = " + haus_hoehe.ergebnis_2 + " m")> setzt wieder die
Instanziierung der Klasse <Haus> zum Objekt <Haus> mit der Instanzvariablen <haus_hoehe> voraus, sodass man
nur die Laufschriftanzeigen „1a) " 11“ und „1b) " 11“ angezeigt bekommt. Auch hier wird die
nachfolgende Methode <berechne_Haushoehe(self, hoehe)> nicht explizit aufgerufen, sodass auch weiter keine
diesbezügliche Laufschriftanzeige
erfolgt! Abschließend wird aber
noch die Laufschriftanzeige „3a.) haus_hoehe = 11 m" angezeigt! Das 5.
Statement <basic.show_string("3b.) haus_hoehe = " setzt ebenfalls die
Instanziierung der Klasse <Haus> zum Objekt <Haus> mit der Instanzvariablen <haus_hoehe> voraus, sodass man
wegen des Statements <haus_hoehe : Haus =
Haus(11)>
als Erstes die Laufschriftanzeigen „1a) " 11“ und „1b) " 11“ angezeigt bekommt. Im Gegensatz zum 4.
Statement wird aber anschließend die Methode
<berechne_Haushoehe(self, hoehe)> mit dem Parameter
bzw. der instanziierten Variablen
<haus_hoehe.hoehe> = 6 + 3 = 9 direkt
aufgerufen. Und zwar mit den Laufschriftanzeigen
„2a) " 6“ und „2b) " 9“. Da die Methode <berechne_Haushoehe(self, hoehe)> über das Rückgabe-Statement
<return self.ergebnis_1> verfügt, wird das Berechnungsergebnis der instanziierten
Variablen <self.ergebnis_1> an das aufrufende Hauptprogramm zurückgeliefert, sodass
dieses Statement Nr. 5 die Laufschriftanzeige „3b.) haus_hoehe = 9 m" zur Folge hat! Wenn man alle Statements im Hauptprogramm
auf einmal, d.h. hintereinander, zur Ausführung bringt (siehe roter Kasten oben), dann hat dies zweifellos zur
Folge, dass Laufschriftanzeigen
innerhalb ·
der Funktion <__init__()> oder ·
der Methode <berechne_Haushoehe(self, hoehe)> mehrfach angezeigt werden, sodass man schnell
den Überblick verlieren kann. - Vererben
und Erben von Eigenschaften, Fähigkeiten einer Klasse zur nächsten Bisher verhielt es sich so, dass mit dem ·
Statement <vol1 : Haus_1 =
Haus_1(12, 6)>
und den beiden Parametern 12 (= Länge L) und 6 (= Breite B) zunächst
nur die Grundfläche = L x B in der <init>-Funktion berechnen ließ. Mittels des ·
Statements <vol1.berechne_Hausvolumen_1(3)> ließ sich in der Methode <berechne_Hausvolumen_1(self, hoehe_1)> dann auch noch das Volumen
vom Objekt Haus_1 berechnen. Das ist natürlich etwas
umständlich. Demzufolge ist es nur eine Frage der Zeit, dass man das Objekt Haus_1
z.B. um die Berechnung des umbauten Volumens
erweitern möchte. Aber
anstelle das Objekt Haus_1 abzureißen und mit dem Objekt Haus_2 neu zu
bebauen, bietet es sich an, das Objekt Haus_1 um einen entsprechenden Anbau zum Objekt Haus_2 zu erweitern: (siehe rote Kästen): (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_58.py“) Wie man im obenstehenden Screenschot sieht,
wird beim Objekt der Klasse <Haus_2> als Erstes der Wert
= 0 m^3 der Variablen <self.volumen_2> angezeigt (siehe dunkelgrüner Kreis) und dann erst als
Zweites der Wert = 150 m^3 der lokalen Variablen <volumen_2> (siehe blauer
Kreis).
Der Grund dafür ist der, dass die ·
Funktion <__init__(self, laenge_2, breite_2,
hoehe_2) über keinen <return()>-Befehl verfügt, sodass diese
quasi erst im Nachgang eingelesen
wird!
Das obenstehende Programm wird umstrukturiert, indem eine strikte Aufgabenteilung vorgenommen
und entsprechend programmiert wird. Und zwar soll in der Klasse <Haus_1> mit der Methode <berechne_Grundflaeche_1(self, laenge_1, breite_1)> nur die Grundfläche
des Hauses und in der Klasse <Haus_2> mit der Methode <berechne_Hausvolumen_2(self,
hoehe_2)> soll nur das umbaute Volumen des Hauses berechnet werden. Wenn also das Volumen berechnet werden soll, dann muss zuvor die Grundfläche des Hauses berechnet
werden, da sich das Volumen aus dem Produkt von Grundfläche * Höhe berechnet. Demzufolge muss also vor
der eigentlichen Volumenberechnung die Berechnung der Grundfläche gemäß der Methode <berechne_Grundflaeche_1(self,
laenge_1, breite_1)> in der Klasse <Haus_1> erfolgen. Und zwar mittels des ·
Methodenaufrufs <grundflaeche_2 = vol1.berechne_Grundflaeche_1(vol1.laenge_1, vol1.breite_1)>, der übrigens den Ergebniswert der Grundflächenberechnung
zunächst an die Variable <grundflaeche_2> zurückliefert: (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_59.py“) Im obenstehenden Sourcecode tragen alle Variablennamen, die innerhalb der Klasse <Haus_1> programmiert wurden und
mit der Berechnung der Grundfläche zu tun haben mit der Endsilbe „_1“
versehen, während die Variablennamen innerhalb der Klasse <Haus_2> , die mit der Berechnung des umbauten Volumens zu tun haben mit der Endsilbe „_2“ versehen wurden! Da sich
alle <self>-Methoden wegen der Kopplung an die jeweilige Instanzklasse
<Haus_1> oder <Haus_2> beim Programmstart
nicht automatisch zusammen mit dem Hauptprogramm starten, muss man
diese explizit im Hauptprogramm
oder z.B. in der Methode <berechne_Hausvolumen_2(self, hoehe_2)> aufrufen und ausführen (siehe roter Kasten im Bild oben). - Bisher verhielt es sich so, dass wir den Kopf der Klasse <Haus_1> oder <Haus_2> stets mittels der <init()>-Funktion konfiguriert haben
(siehe roter Kasten),
um dem Objekt der Klasse ein oder mehrere Parameter mit auf den Weg geben zu können: ·
Statement <vol1 : Haus_1 =
Haus_1(12, 6)> ó <class
Haus_1:> Dabei kann man der erbenden Klasse <Haus_2> nicht nur die Eigenschaften, Funktionen und Methoden der
vererbenden Klasse <Haus_1> mit auf den Weg geben, d.h. vererben,
sondern auch deren (Eingangs-)
Parameter
im Kopf der Klasse <Haus_1(12, 6)>,
·
Statement <vol2 : Haus_2 =
Haus_2(10, 5)> ó <class
Haus_2(Haus_1):> sodass die Parameter im Kopf der Klasse <Haus_2(10, 5)> wegen des geänderten Kopfes der Klasse <Haus_2(Haus_1)>
wegen des Überschreibens(!) nicht wirksam
werden: ·
Statement <class Haus_2(Haus_1):> (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_60.py“) Wie man im obenstehenden Quellkode im kleinen,
grünen Kasten <(Haus_1)>)
sieht, wird die Klasse <Haus_2> mittels des ·
Statements <class Haus_2(Haus_1):> bereits auf die Erbschaft von der Klasse <Haus_1> vorbereitet. Aber es
gehört natürlich noch mehr dazu, wie wir gleich sehen werden. Wenn man das obenstehende Programm „joy-car_teil_02_prog_60.hex“
startet, dann übernimmt die Klasse <Haus_2> mit dem ·
Statement <grundflaeche_2 = vol1.laenge_1 * vol1.breite_1> die eingangsseitigen Parameterwerte 12 und 6 der Klasse <Haus_1>, sodass sich das Volumen
des Hauses wie folgt berechnet: Volumen V = Grundfläche
G x Höhe h
= Länge x Breite x Höhe = 12 m x 6 m x 3 m =
72 m^2 x 3 m = 216 m^3
(Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_61.py“) Die oben im Quellkode zu sehende Funktion
<berechne_Grundflaeche_1A(laenge_1, breite_1)> (siehe roter Kasten) ist nicht an die
Klasse <Haus_1> gekoppelt, steht für sich ganz allein und lässt sich dem
demzufolge nur innerhalb der Klasse
<Haus_1> wie folgt aufrufen: ·
Statement <berechne_Grundflaeche_1A(12, 6)>.
- Wie man im nachfolgenden Sourcecode des Programms „joy-car_teil_02_prog_62.py“
sieht, lässt sich die vererbte ·
Methode <self.berechne_Grundflaeche_1B(laenge_2, breite_2)> auch mit beliebig anderen Parameternamen nebst Werten
aufrufen (siehe grüner Pfeil mit den 7 7 ): (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_62.py“) Wir wenden uns wieder der ·
Funktion <berechne_Grundflaeche_1A(laenge_1, breite_1)> der Klasse
<Haus_1> zu (siehe roter Kasten im Bild oben), die
tatsächlich vollkommen eigenständig ist und nicht mittels <self> an die Klasse <Haus_1> gekoppelt ist,
weshalb diese eben keine Methode
ist! Wegen der Isoliertheit der Funktion haben wir nach wie vor das
Problem, dass sich diese nur innerhalb der Klasse <Haus_1> aufrufen und
ausführen lässt. Ein weiteres Problem besteht darin, dass sich
beim Funktionsaufruf mit dem ·
Statement <grundflaeche_1 = berechne_Grundflaeche_1A(12, 6)>
nur konstante Werte, aber eben keine Werte von Variablen als Parameter
dem Funktionsaufruf mit auf den Weg geben
lassen (siehe roter Kasten im Bild oben)! Um diese Nachteile
aus dem Weg zu räumen, und um zu einem besseren Verständnis des Ganzen zu
kommen, lagern wir die ·
Funktion <berechne_Grundflaeche_1A(laenge_1, breite_1)> kurzerhand in die neue Klasse <Haus_3> aus und benennen
diese zur ·
Methode <berechne_Grundflaeche_1C(self)> um: (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_63.py“) Wie man im obenstehenden Quellkode sieht, ist
die ursprüngliche ·
Funktion <berechne_Grundflaeche_1A(laenge_1, breite_1)> wegen der Kopplung
an die neue Klasse <Haus_3> mittels <self>-Parameter jetzt nicht
mehr isoliert ·
Methode <berechne_Grundflaeche_1C(self)>, sodass sich auf diese von außen, d.h. z.B. vom
Hauptprogramm aus, mittels des ·
Statements <vol3.berechne_Grundflaeche_1C()> aufrufen und ausführen lässt (siehe blauer
Kasten
im Bild oben). Da sich im Kopf der Methode <berechne_Grundflaeche_1C(self)> weiter keine Parameter
mit auf den Weg geben lassen, muss man
die zu berechnenden Werte mittels
der Variablen <vol3.laenge_3> und <vol3.breite_3> quasi von außen zuführen bzw. zugänglich machen (siehe pinkfarbener
Kasten im Bild oben)! Als inzwischen erfahrener Python-Programmierer gehen wir noch einen Schritt
weiter, indem wir dem obenstehenden Programm noch die ·
Funktion < __init__(self, laenge_3, breite_3)> hinzufügen (siehe pinkfarbener Kasten), (Vergrößern: auf das
Bild klicken! | Programm „joy-car_teil_02_prog_64.py“) sodass sich von nun an auch Werte in Form der Parameter <laenge, breite> dem Aufruf und Ausführen der ·
Methode <berechne_Grundflaeche_1C(self, laenge_3,
breite_3)>, mit auf den Weg geben lassen (siehe unterer blauer
Kasten
im Bild oben)! Im Vergleich mit dem Programm „joy-car_teil_02_prog_62.py“
bietet das weiter entwickelte Programm
„joy-car_teil_02_prog_64.py“
den Vorteil, dass sich die Klasse <Haus_3> mit nur einem ·
Statement <super().__init__(laenge_3,
breite_3)>
um die Eigenschaft
des Vererbens erweitern lässt! - |
|
||||
|
[
Home ]
[ Seitenanfang ] [Teil 1 ] [ Teil 2a ] [ Teil 3 ] [ Teil 4 ] |
|