[ Home ] [ zurück ] [ Seitenende ] [ Teil 1 ] [ Teil 3 ]

 

 

 

micro:bit-Programmieren, Teil 2

 

1.     Einleitung

 

Bekanntlich verfügen alle Menschen über fünf Sensoren, pardon Sinne. So kann der Mensch mit seinen Augen sehen, mit den Ohren hören, mit der Zunge schmecken, mit der Nase riechen und mit den Fingerspitzen der Hände fühlen. Im Allgemeinen funktionieren unsere Sensoren recht zuverlässig, kann man sich auf diese verlassen. Manchmal schwinden uns aber auch die Sinne, wenn wir bei Feierlichkeiten zu viel Alkohol getrunken haben. Dann fangen die Buchstaben, englisch characters, an zu tanzen, lassen sich Zeichenketten, englisch strings nicht mehr richtig erkennen, zuordnen und interpretieren:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wenn man aber weder betrunken ist, noch unter Halluzinationen leidet, dann erkennt man sofort, dass es sich bei dem Textstring „!dlroW olleH im Programm „microbit_teil_02_prog_01.hex mit dem Sourcecodemicrobit_teil_02_prog_01.js einfach nur um die rückwärts von rechts nach links geschriebene Zeichenfolge Hello World!“, d.h. auf deutsch „Hallo Welt!“ handelt.

 

Linkshändern, d.h. Menschen deren beiden Gehirnhälften anders herum „verdrahtet“ sind und die deshalb bevorzugt mit der linken Hand schreiben, müsste man eigentlich auch die Gelegenheit geben, von rechts nach links, d.h. spiegelbildlich zu schreiben, damit diese mit der Hand nicht die frische Tinte verschmieren.

 

Schriftsetzer bei der Zeitung oder beim Buchdruck, deren Beruf aber wegen der Computerdrucksetzung inzwischen ausgestorben ist, musste die Druckplatten noch stets in Spiegelschrift anfertigen, hatten also mit dem Rückwärtsschreiben und -lesen überhaupt kein Problem.

 

Dem Computer, d.h. unserem micro:bit“-Rechner macht es übrigens nichts aus, Textstrings spiegelbildlich von rechts nach links zu lesen und sie in der richtigen Reihenfolge wieder auf dem Display, d.h. der „5 x 5 LED-Matrix“ anzuzeigen. Allerdings macht der Computer immer nur das, was man ihm beigebracht bzw. programmiert hat. Und die Laufschrift auf dem „Display“ geht natürlich nach wie vor von rechts nach links.

 

2.     Vom Block-Programmieren zu JavaScript

 

Wie bereits im Kapitel „micro:bit-Programmieren, Teil 1 gezeigt und erklärt wurde, verfügt das Block-Programmieren leider nur über einen abgespeckten basic“-Befehlsvorrat, sodass sich mit diesem verschiedene Dinge wider Erwarten nicht mit den Blocksymbolen programmieren lassen.

 

Dies ist besonders ärgerlich und kontraproduktiv, wenn man im basic“-Befehlsvorrat nach einem bestimmten Befehl sucht, diesen nicht findet, da nicht implementiert und deshalb eher früher als später auf JavaScript ausweichen muss. -

2.1     Spiegelverkehrten Textstring rückwärts auslesen

Wenn man also den spiegelbildlichen Textstring !dlroW olleH auf der Display richtig lesbar von links nach rechts anzeigen will, dann muss man diesen rückwärts, d.h. von hinten nach vorn auslesen. Dazu muss man die Länge, engl. length, des Textstrings ermitteln. Und zwar mit dem JavaScritp“-Statement txtstr.length bei dem an die eigentliche Textvariable txtstr einen Punkt gefolgt von der Angabe length anfügt:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Bei der Längenangabe eines Textstrings, d.h. dem Inhalt der Textvariablen txtstr werden auch engl. spaces, d.h. ein oder mehrere Leerschritte in Form von Leerzeichen „ “ mitgezählt!

 

Wie man oben im Screenshot sieht, werden die Variablen n und txtstr erst deklariert und anschließend initialisiert. [ Video 1 ]

 

Dabei legt man beim Deklarieren fest, von welchem Typ die jeweilige Variable sein soll. Demzufolge ist die Zählvariable n vom Typ int8, engl. „integer“, d.h. ganzzahlig positiv (oder negativ).

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie wir jetzt wissen, handelt es sich bei der Datenangabe Typ ‚int8’ im Programm „microbit_teil_02_prog_02.hex“ und dem Sourcecodemicrobit_teil_02_prog_02.js“ um eine Alias-Angabe für den Typ int im Sinne von ‚integer’, d.h. ganzzahlig positiv oder negativ.

 

Leider wird die Typangabe int vom micro:bit“-Rechner bzw. der Microsoft „MakeCode“-Programmierumgebung wider Erwarten nicht unterstützt, sodass man stattdessen die Typangabe ‚int8’ verwenden muss. -

 

Der Windows“-eigene Taschenrechner lässt sich übrigens auf „Programmierer“ umschalten, sodass sich mit diesem ganz bequem dezimale Zahlen in binäre, oktale oder hexadezimale (und umgekehrt) umrechnen lassen:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Was jetzt noch fehlt, ist die rückwärts zählende Schleife zwecks Anzeige der einzelnen Buchstaben des spiegelbildlichen Textstring „!dlroW olleH:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Bei der im Quelltext stehenden while“-Schleife fällt auf, dass die Textvariable txtstr in Form eines sogenannten „Substrings“ der Länge von nur einem Zeichen an der Position n wiedergegeben wird. Dabei verändert sich die Position n eines darzustellenden Zeichens aus dem Textstring von Position 12 (ganz rechts) auf Position 1 (ganz links), sodass der spiegelbildliche Textstring in Form der einzelnen Buchstaben quasi von rechts nach links angezeigt werden.

 

Im Prinzip aber werden die einzelnen Buchstaben so dargestellt wie bei der Laufschrift selbst; sie werden dabei aber nur rückwärts aus dem Textstring ausgelesen!

 

Mit dem Programm „microbit_teil_02_prog_02.hex und dem Sourcecodemicrobit_teil_02_prog_02.js können Sie das Ganze selbst ausprobieren! -

 

Wenn man die flüchtige Laufschrift „einfangen“ und das Ergebnis sichern möchte, dann muss man das Programm noch entsprechend erweitern und den angezeigten Inhalt in Form der einzeln angezeigten Buchstaben in einem separaten Textstring wie folgt aufaddieren und abspeichern:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Das Programm „microbit_teil_02_prog_03.hex und den Sourcecodemicrobit_teil_02_prog_03.js kann man sich im Browser anzeigen lassen oder mittels rechter Maustaste herunterladen. -

2.2     Von der „while“- zur „for“-Schleife

Neben den while“-Schleifen gibt es auch noch die for“-Schleifen, die allgemein beliebter sind und sich leichter programmieren und verstehen lassen, weil man mit diesen innerhalb der Schleife meistens nur von null an bis zu einem bestimmten Endwert hoch zählt.

 

Im vorliegenden Fall geht es bei der for“-Schleife aber nur darum, dass die Schleife entsprechend der Stringlänge der Variablen txtstr = „!dlroW olleH insgesamt bis zu 12 mal durchlaufen wird, wobei es keine Rolle spielt, ob dabei die Schleife hoch- oder runtergezählt wird.

 

Beim zwölfmaligen Schleifendurchlauf braucht man dann aber eine weitere Variable, um mit dieser die Position eines einzelnen Zeichens innerhalb des Textstrings anzulaufen und abzufragen. Dabei handelt es sich um die (Positions-) Variable m mit der der Textstring txtstr rückwärts durchlaufen wird:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Das Programm „microbit_teil_02_prog_04.hex und den Sourcecodemicrobit_teil_02_prog_04.js kann man sich im Browser anzeigen lassen oder mittels rechter Maustaste herunterladen. -

 

Wenn man mit einer for“-Schleife rückwärts zählen will, dann muss man diese von Grund auf besser verstehen.

 

Wie man bei der for“-Schleife im obenstehenden Programm sieht, stehen in der runden Klammer ( … ) insgesamt drei Terme, als da sind: (n = 0; n <= txtstr.length; n++), die jeweils durch ein Semikolon voneinander getrennt sind:

 

1.     Term n = 0

bei diesem handelt es sich um den
Anfangswert, von dem aus entweder hoch- oder runtergezählt wird!

 

2.    Term n <= txtstr.length

bei dem es sich um eine
Bedingung handelt, die vor jedem Schleifendurchlauf abgefragt wird!

Dazu muss man wissen, dass es sich bei
for“-Schleifen um sogenannte Kopf gesteuerte Schleifen handelt bei denen die Bedingung stets zu Beginn, also bevor die Schleife ein weiteres Mal durchlaufen wird, erfüllt sein muss!

Wird die
Bedingung nicht erfüllt, wird die Schleife gleich zu Beginn, d.h. noch im Schleifenkopf abgebrochen!

 

3.     Term n++

bei diesem handelt es sich um den
Wert, um den der Schleifenzähler n nach jedem Schleifendurchlauf erhöht (oder verringert) wird: n = n + 1 bzw. n++

 

So, jetzt dürfte es nicht mehr so schwer fallen, die drei Terme so zu programmieren, dass sich mit diesen ein entsprechender Schleifenkopf zu einer for“-Schleife mit der sich herunterzählen lässt, zu gestalten:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie man im obenstehenden Sourcecode sieht, braucht man jetzt zum zwölfmaligen Schleifendurchlauf keine weitere (Hilfs-) Variable m mehr, um mit dieser die Position eines einzelnen Zeichens innerhalb des Textstrings anzulaufen und abzufragen, da wir jetzt mit der for“-Schleife rückwärts zählen!

 

Selbstverständlich lässt sich das Ganze mit dem Programm „microbit_teil_02_prog_05.hex auch ausprobieren und der Sourcecodemicrobit_teil_02_prog_05.js wie gewohnt im Browser anzeigen oder mittels rechter Maustaste herunterladen. -

 

So, jetzt haben wir ganz nebenbei auch noch gelernt, was eine while“- von einer for“-Schleife unterscheidet und wie man mit einer for“-Schleife auch rückwärts zählen kann.

[ Video 2 ]

2.3     Umschaltbare Textstring-Anzeige

Wie im obenstehenden Programm zu sehen ist, haben wir es mit zwei Stringvariablen txtstr und new_txtstr zu tun.

 

Dabei enthält die Stringvariable txtstr den spiegelverkehrten Textstring !dlroW olleH und die Stringvariable new_txtstr den umgewandelten Textstring Hello World!“.

 

Diesbezüglich bietet es sich an, dass man die Textanzeige mit der „5 x 5 LED-Matrix“ umschaltbar macht, sodass beim Tastendruck auf den Taster A der spiegelverkehrte Textstring „!dlroW olleH als Laufschrift angezeigt wird und beim Tastendruck auf den Taster B der umgewandelte Textstring Hello World!“:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Damit sich die beiden Taster A und B jederzeit betätigen lassen, werden diese mit dem Statement basic.forever(() => { … }) quasi als Endlos“-Schleife eingebunden.

 

Der Sourcecodemicrobit_teil_02_prog_06.js lässt wie üblich direkt im Browser anzeigen oder als Programm „microbit_teil_02_prog_06.hex im „micro:bit“-Rechner ausführen.

2.4     Zusammenfassung zweier Textstrings zu einem Array

Das englische Wort array lässt sich wörtlich mit „Feld, Ansammlung oder Aufstellung“ übersetzen. Dabei kann man sich durch aus ein Spargelfeld vorstellen, das sich aus mehreren Spargelreihen zusammen setzt. Da sich unser dezimales Zahlensystem vom hindu-arabischen Zahlensystem ableitet und es in diesem bereits die Zahl null gab, bekommt die erste Spargelreihe in unserem Array die Null als Index, um sie von anderen Spargelreihen nebst fortlaufendem Index unterscheiden zu können.

 

Im nachfolgenden Programm microbit_teil_02_prog_07.hex mit dem Quellkode microbit_teil_02_prog_07.js wird die ursprünglich benutzte Stringvariable txtstr mit dem spiegelverkehrten Textstring „!dlroW olleH umbenannt in die Stringvariable txtstr_1 und die zunächst leere Stringvariable new_txtstr wird zur Stringvariablen txtstr_2.

 

Des Weiteren wird ein Array namens str_array: string[]“ wie folgt deklariert:

 

·        var str_array: string[]

und später mit den beiden Stringvariable
txtstr_1 und txtstr_2 initialisiert:

·        str_array =[txtstr_1, txtstr_2]

 

Dabei ist das Array bzw. die var str_array: string[] zunächst unbestimmt, kann das Array praktisch beliebig viele Elemente aufnehmen, auch nachträglich:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Im Programm microbit_teil_02_prog_08.hex mit dem Quellkode microbit_teil_02_prog_08.js wird dann das Array namens str_array: string[]“ beim Konvertieren des spiegelbildlichen Textstrings mit txtstr_1 = "!dlroW olleH" in der for“-Schleife auch entsprechend benutzt:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

[ Video 3 ]

 

Beim Programm microbit_teil_02_prog_09.hex mit dem Quellkode microbit_teil_02_prog_09.js stellt sich die Frage, weshalb beim Drücken des Tasters A nun plötzlich nicht mehr der Text „!dlroW olleH, sondern vielmehr „Hallo Welt!“ im Display, d.h. auf der „5 x 5 LED-Matrix“ angezeigt wird:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Der Grund dafür, dass beim Betätigen des Tasters A jetzt plötzlich der Schriftzug „Hallo Welt!“ angezeigt wird und nicht mehr !dlroW olleH, ist der, dass es sich bei dem Programmblock basic.forever(() => { … })“ um einen sogenannten Konstruktor innerhalb des Hauptprogramms handelt. [ Video 4a ]

 

Im vorliegenden Fall handelt es sich sogar um einen besonderen Konstruktor namens forever, da dieser den in der geschweiften Klammer { … } enthaltenen Programmkode fortwährend im Hintergrund (des Hauptprogramms) ausführt, sodass sich die Taster A und B jederzeit betätigen lassen.

 

Man könnte auch sagen, dass es sich bei dem forever“-Konstruktor um eine Ereignis gesteuerte Programmierung handelt bei der das Programm stets im Hintergrund lauert und darauf wartet, dass etwas passiert, um dann sofort darauf zu reagieren. Das Ereignis selbst wäre dann aber nur der Tastendruck auf den Taster A oder B.

 

Da ein Konstruktor ein in sich geschlossenes (Teil-) Programm ist, lassen sich in ihm auch eigene, d.h. lokale Variable deklarieren und initialisieren, die nach außen zu den anderen Programmteilen hin abgeschirmt und nicht ohne Weiteres von außen zugänglich sind!

2.5     Strukturiertes Programmieren mit Funktionen

Programmiertechnisch lässt sich eine Funktion als ein besseres, flexibleres Unterprogramm bezeichnen. Dabei handelt es sich aus der Sicht des Hauptprogramms um eine Black Box in die man etwas hinein gibt, den Input anhand von Regeln ähnlich einer Rezeptur intern verarbeitet, gestaltet, organisiert und strukturiert, sodass sich am Ausgang ein Output einstellt, dessen Ausgangsprodukt einen höheren Mehrwert als das Eingangsprodukt hat. Dabei kann das Ausgangsprodukt auch neue Eigenschaften und Funktionen enthalten, die es zuvor so noch nicht gab. Entscheidend bei einer Funktion ist, dass man aus Sicht des Hauptprogramms gar nicht weiß und auch gar nicht wissen will, was in der Funktion als Black Box vor sich geht. Hauptsache es kommt aus der Black Box etwas Wertvolleres heraus, als man in diese zuvor hineingegeben hatte. Außerdem soll die Funktion das Hauptprogramm nicht stören und in Ruhe lassen, soll das Geschehen in der Funktion als Black Box abgeschirmt sein und dabei das Hauptprogramm entlasten. Wenn dabei aber trotzdem Fehler passieren, dann bitte schön nur in der Funktion ohne das Hauptprogramm dadurch zu beeinflussen oder sogar zum Absturz zu bringen.

 

Der Hauptvorteil einer Funktion ist aber der, dass man bestimmte und immer wieder vorkommende Vorgänge, Schemata und Routinen in der Funktion zusammenfasst, d.h. aus dem Hauptprogramm auslagert, wobei sich die Funktion von überall her und beliebig oft aufrufen lässt.

 

Wie man im Programm microbit_teil_02_prog_10.hex mit dem Quellkode microbit_teil_02_prog_10.js sieht, muss eine Funktion nicht nur programmiert werden, sondern auch explizit aufgerufen werden, da sie sich nicht von allein, z.B. nach dem Programmstart eines Programms startet:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie man im obenstehenden Sourcecode sieht, werden im Kopf der Funktion function starteProgramm() { … }“ (siehe roter Kasten) keine Variablen oder Variableninhalte an diese übergeben. Demzufolge ist runde Klammer () leer.

 

Würde man der Funktion function starteProgramm() { … }“ (siehe roter Kasten) entsprechende (Variablen-) Inhalte mit auf den Weg geben wollen, dann müsste dies bereits mit dem Funktionsaufruf starteProgramm() veranlasst werden. Da die runde Klammer () beim Funktionsaufruf aber leer ist, werden keine Inhalte an die Funktion übergeben!

 

Im Programm microbit_teil_02_prog_11.hex mit dem Quellkode microbit_teil_02_prog_11.js erfolgt jetzt aber der Funktionsaufruf mittels der Übergabe einer Textmitteilung, eines Textstrings statt:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie man oben im Programm sieht, wird die Variable str_einlesen im Kopf der Funktion function starteProgramm(str_einlesen: string) deklariert, aber nicht initialisiert, da dies bereits mit dem Funktionsaufruf starteProgramm(„Dies ist eine Funktion!“) erfolgt!

 

Dieser Umstand ist nicht nur logisch, sondern auch nachvollziehbar: Würde man nämlich die Variable str_einlesen im Kopf der Funktion function starteProgramm(var str_einlesen: string) mittels var deklarieren, dann bekäme die Variable str_einlesen beim Deklarieren bereits den Wert null, d.h. leer mit auf den Weg, sodass sich der Textstring „Dies ist eine Funktion!“ nicht mehr übergeben ließe und zu einer Fehlermeldung führen würde! [ Video 4b ]

 

Wie man im Programm microbit_teil_02_prog_12.hex mit dem Quellkode microbit_teil_02_prog_12.js sieht, lässt sich beim Funktionsaufruf auch der spiegelbildliche Textstring „!dlroW olleH der Variablen txtstr_1 an die Funktion function starteProgramm(str_einlesen: string) wie folgt übergeben:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie man im Programm microbit_teil_02_prog_13.hex mit dem Quellkode microbit_teil_02_prog_13.js sieht, lässt sich der Funktionsaufruf starteProgramm(txtstr_1) auch von außerhalb des Hauptprogramms, nämlich z.B. im forever“-Konstruktor vornehmen:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie man im obenstehenden Quellkode sieht, wird mit dem Funktionsaufruf starteProgramm(txtstr_1) der Variableninhalt „Hallo Welt!“ der lokalen Variablen txtstr_1 des forever“-Konstruktors an die Funktion übergeben!

 

Außerdem wird die Funktion starteProgramm(txtstr_1) erst dann aufgerufen, wenn der Anwender den Taster A betätigt! -

 

Wie man im Programm microbit_teil_02_prog_14.hex mit dem Quellkode microbit_teil_02_prog_14.js sieht, lässt sich beim Funktionsaufruf der Funktion function starteProgramm(str_einlesen: string) nicht nur ein Textstring oder der Wert einer Variablen übergeben, sondern lassen sich am Ende der Funktion mit dem Statement return (str_ausgeben) auch ein Textstring oder der Wert einer Variablen an den aufrufenden forever“-Konstruktor wieder zurück geben.

 

Da das Zurückgeben von Daten und Dateninhalten mittels der Variablen str_ausgeben im Statement return (str_ausgeben) erfolgt, also von der Funktion function starteProgramm(str_einlesen: string) veranlasst wird, muss und kann das Deklarieren der (Rückgabe-) Variablen str_ausgeben nur innerhalb der Funktion erfolgen. Dabei gilt es quasi zwischen Ursache und Wirkung zu unterscheiden, da sich der Dateninhalt der Variablen str_ausgeben nur mit dem Statement return (str_ausgeben) zurückgeben lässt und zwar auch nur dann, wenn die Variablen str_ausgeben zuvor innerhalb der Funktion deklariert und initialisiert wurde:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Besonders interessant ist dabei nun, dass sich der aufrufende forever“-Konstruktor gar nicht für die Datenrückgabe der Funktion mittels des Statement return (str_ausgeben) interessiert bzw. auch gar nichts davon weiß bzw. wissen kann, da es für die Aufnahme des Datenrückflusses überhaupt keine Variable gibt, sodass die Datenrückgabe ins Leere geht!

 

Wenn sich aber der aufrufende forever“-Konstruktor gar nicht für die Datenrückgabe der Funktion mittels des Statement return (str_ausgeben) interessiert, dann könnte man diese ja auch weglassen!

 

Diesbezüglich stellt aber gleich die Frage, wozu der Rücksprung mittels des return“-Statements überhaupt gut sein soll! Ganz einfach, damit die aufrufende und ausführende Funktion function starteProgramm(str_einlesen: string) wieder veranlassen wird und mit dem Programmablauf dort weitergemacht wird, von wo man zuletzt aus verzweigt ist, nämlich im forever“-Konstruktor!

 

Ob es nach dem Rücksprung aus der Funktion function starteProgramm(str_einlesen: string) dann tatsächlich noch zur Datenübergabe kommt oder nicht, ist also aus der Sicht der Funktion uninteressant, da diese ohnehin keinen direkten Einfluss darauf hat!

 

Aber es bleibt spannend, müssen wir noch etwas Detektivarbeit leisten und uns Gedanken machen, wie man den veranlassten Rücksprung aus der Funktion function starteProgramm(str_einlesen: string) tatsächlich überprüfen kann. Also bleibt uns nichts anderes übrig, als im aufrufenden forever“-Konstruktor noch die Variable txtstr_1 für die Datenübernahme zu programmieren (siehe Programm microbit_teil_02_prog_15.hex mit dem Quellkode microbit_teil_02_prog_15.js):

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Mit dem obenstehenden Programm und der Variablen txtstr_1 haben wir zwar die Voraussetzung für die Datenübernahme beim Rücksprung aus der Funktion function starteProgramm(str_einlesen: string) geschaffen, aber ob das auch in der gewünschten Weise wirklich funktioniert wissen wir bis jetzt trotzdem noch nicht!

 

Erst wenn wir uns im Programm microbit_teil_02_prog_16.hex mit dem Quellkode microbit_teil_02_prog_16.js) mittels des Funktionsaufrufs starteProgramm(txtstr_1) tatsächlich den Variableninhalt der lokalen Variablen txtstr_1 anzeigen lassen, haben wir die Gewissheit, dass der Rücksprung aus der Funktion function starteProgramm(str_einlesen: string) nebst Datenübergabe an die lokale Variable txtstr_1 tatsächlich in der gewünschten Art und Weise funktionieren:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Jetzt wissen wir endlich wie leistungsfähig aber auch komplex Funktionen sein können, und dass sich diese auch per Tastendruck auf den Taster A aufrufen und ausführen lassen.

 

Ferner wissen wir, dass es nicht nur globale Variablen, die meistens im Hauptprogramm deklariert und/oder initialisiert werden, gibt, sondern auch lokale Variablen, die in Konstruktoren oder Funktionen eingesetzt werden und vom Hauptprogramm aus nicht erreichbar und nutzbar sind, .da sie quasi abschirmt sind.

 

Abschließend gibt es aber noch etwas Interessantes festzuhalten. Wahrscheinlich ist Ihnen bereits kurz nach dem Programmstart aufgefallen, dass dieses angeblich schon wieder beendet wurde (siehe Statement basic.showString("Programmende!")).

 

Wie kann das sein? Schließlich lassen sich trotz der Meldung Programmende!“ noch immer die Taster A und B betätigen und die im forever“-Konstruktor programmierten Reaktionen darauf anzeigen!

 

Ganz einfach! Nach dem Programmstart werden alle Statements linear, d.h. der Reihe nach, aufgerufen und abgearbeitet. So auch der forever“-Konstruktor, der ja still und leise im Hintergrund vor sich hin werkelt und ständig die beiden Taster A und B abfragt, ob diese eventuell gedrückt wurden.

 

Demzufolge nach wurde zwar das Hauptprogramm komplett abgearbeitet und quasi auch beendet, obwohl es sich per Tastendruck auf einen der beiden Taster A oder B wieder zum Leben erwecken lässt. Totgeglaubte leben halt doch länger! [ Video 5 ]

2.6     Von der Funktion zur Methode mit Funktionsobjekt

Wie man in JavaScript eine Funktion programmiert wissen wir. Dass sich eine Funktion nicht automatisch zusammen mit Hauptprogramm startet, sondern explizit durch den Aufruf des Funktionnamens aufgerufen werden muss, wissen wir auch.

 

Aber erinnern wir uns trotzdem noch mal daran, was eine Funktion ist, was eine Funktion ausmacht und wozu man sie verwendet. Das Charakteristische einer Funktion ist, dass man dieser beim Aufrufen derselben einen, mehrere oder auch verschiedene Werte, Ausdrücke, Zeichenstrings oder boolesche Werte im Sinne von „true“ (= richtig) oder „false“ (= falsch) z.B. in Form von Variablen mit auf den Weg gibt, d.h. einliest. In der Funktion wird dann festgelegt, was mit den eingelesenen Variableninhalten passieren soll, wie diese verarbeitet, verknüpft und ausgewertet werden sollen. Anschließend lässt sich dann das Ergebnis als Reaktion auf die Verarbeitung und Auswertung wieder an das aufrufende Programm zurückgeben. Demzufolge kann man eine Funktion mit einer Black Box vergleichen, in die man etwas hinein gibt und als Ergebnis etwas ähnliches oder gänzlich anderes heraus bekommt. Kurz gesagt, sorgt eine Funktion dafür, dass etwas in der gewünschten, beabsichtigten Weise, nach bestimmten, programmierten Anweisungen einfach nur funktioniert.

 

Koppelt man eine Funktion an eine Variable, dann spricht man von einer Methode!

 

>> Methoden (englisch method oder member function) sind in der objektorientierten Programmierung Unterprogramme (in der Form von Funktionen oder Prozeduren), die das Verhalten von Objekten beschreiben und implementieren. Über die Methoden des Objekts können Objekte untereinander in Verbindung treten. << (Quelle: Wikipedia)

 

Eine Methode legt also die Vorgehensweise, das wie, womit und wodurch fest und beeinflusst dabei das Verhalten des betreffenden Objekts!

 

Bevor wir unsere Funktion function starteProgramm(str_einlesen: string) in eine Methode umwandeln, betreiben wir noch etwas Programmkosmetik, hübschen wir uns auf, indem wir noch etwas Schminke auftragen und den Lippenstift nachziehen. Dabei dient die Programmkosmetik der besseren Lesbarkeit des Quellkodes, um Missverständnissen vorzubeugen.

 

Wie wir ja inzwischen wissen, wird neben dem eigentlichen Hauptprogramm „microbit_teil_02_prog_17“ auch noch der Konstruktor basic.forever(() => { … })“ als Hintergrundprogramm gestartet, das auch dann noch arbeitet, wenn das Hauptprogramm längst abgearbeitet und quasi beendet wurde.

 

Aber wie wir ferner wissen, lässt sich das Hauptprogramm bzw. lassen sich Teile davon wieder zum Leben erwecken, wenn man den Taster A betätigt und mittels Tastendruck die Funktion function starteProgramm(str_einlesen: string) startet, die ja ein Teil des Hauptprogramms ist.

 

Deshalb ist das Ende des Quellkodes nicht das Ende des Programms oder das Programmende, da ja noch der Konstruktor basic.forever(() => { … })“ still und leise im Hintergrund vor sich hin werkelt bis der Strom ausfällt!

 

Deshalb lautet jetzt das Ende des Quellkodes im Programm microbit_teil_02_prog_17.hex mit dem Quellkode microbit_teil_02_prog_17.js wie folgt:

 

basic.clearScreen()

basic.showString("Ende Quellkode!")

 

Außerdem benennen wir die

 

Funktion function starteProgramm(str_einlesen: string)

jetzt um in

 

Funktion function starteFunktion(str_einlesen: string),

 

da ja in Wirklichkeit kein neues Programm gestartet wird, sondern nur eine Funktion des Hauptprogramms, engl. abgekürzt „main“. -

 

In der Programmierpraxis bzw. beim Programmieren eines Programms wird es früher oder später vorkommen, dass man z.B. mittels einer Funktion gleich zu Beginn, d.h. direkt nach dem Programmstart des Hauptprogramms ein paar Variablen deklarieren und initialisieren, ein Array mit Dateninhalten füllen oder mittels Programmkode den Status eines Teilprogramms oder einer anderen Funktion usw. abrufen möchte.

 

Zu diesem Zweck müssen wir erreichen bzw. veranlassen, dass der Programmkode der Funktion gleich beim Programmstart still und leise quasi im Hintergrund ausgeführt wird, sodass der Anwender davon überhaupt nichts mitbekommt.

 

Wie wir ja bereits wissen, werden im Hauptprogramm deklarierte und initialisierte, globale Variablen gleich beim Programmstart eingerichtet, sodass sie ab sofort zur Verfügung stehen und nutzen lassen.

 

Wenn wir also erreichen wollen, dass sich die Funktion starteFunktion()“ später beim Programmstart des Hauptprogramms mit startet, dann müssen wir der Funktion im Hauptprogramm eine sogenannte Objektvariable funktion_var zuweisen, die dann später beim Programmstart deklariert und initialisiert wird und dadurch dafür sorgt, dass die Funktion starteFunktion()“ zusammen mit dem Start des Hauptprogramms ausgeführt wird:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Bei dem obenstehenden Statement funktion_var()“ (siehe roter Kasten) handelt es sich um den Funktionsaufruf der Funktion starteFunktion()“, sodass diese direkt beim Programmstart gestartet und ausgeführt wird!

 

Wenn alles so funktioniert, wie wir es uns vorstellen, dann müsste nach dem Programmstart sofort als erstes die Anzeige „Funktion wurde gestartet!“ im Display angezeigt werden und als zweites „Ende Quellkode“. Mit dem Programm microbit_teil_02_prog_18.hex mit dem Quellkode microbit_teil_02_prog_18.js lässt sich das Ganze ausprobieren!

 

Bei der globalen Variablen funktion_var handelt es sich um eine Objektvariable, die entsprechend der Deklaration zur Funktion starteFunktion()“ gehört. Demzufolge kann man auch von einer Funktions-Objektvariablen reden. Die Funktions-Objektvariable funktion_var wird aber erst dann durch die Funktion starteFunktion()“ initialisiert, wenn diese durch das Statement funktion_var()“ gestartet wird.

 

Wie man im Programm microbit_teil_02_prog_19.hex mit dem Quellkode microbit_teil_02_prog_19.js sieht, kann man dem Funktionsaufruf funktion_var("Funktion wird gestartet!“)“ auch einen Textstring mit auf den Weg geben, der von der Funktion starteFunktion(str_einlesen: string)“ eingelesen wird:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Im obenstehenden Quellkode ist noch interessant, dass man sich den Variableninhalt der Variablen str_einlesen ins Boot holen, d.h. in die lokale Variable str_ausgeben holen und dort weiter verarbeiten kann, falls das mal notwendig sein sollte.

 

Wie wir inzwischen wissen, wird die Funktions-Objektvariable funktion_var zunächst nur deklariert (siehe großer roter Kasten oben im Bild) und erst später mittels der Funktion starteFunktion()“ initialisiert, wenn man die Funktion mittels des Methodenaufrufs funktion_var(“Funktion wird gestartet!“) aufruft!

 

Dabei gilt es zu beachten, dass es sich bei der Funktion starteFunktion(str_einlesen: string)“ immer noch um eine Funktion handelt, auch wenn man diese der Objektvariablen funktion_var zuweist. Aber genau durch diese Zuweisung wird die bestehende Funktion zur Methode nebst Methodenaufruf funktion_var(“Funktion wird gestartet!“) erweitert.

 

Da es sich bei der Objektvariablen funktion_var jetzt aber um eine Objektvariable der Methode starteFunktion(str_einlesen: string)“ handelt, benennen wir diese nachfolgend um in Objektvariable methode_starteFunktion.

 

Jetzt wo es sich bei der erweiterten Funktion um eine Methode handelt, die sich mittels Methodenaufruf methode_starteFunktion aufrufen und starten lässt, können wir z.B. auch im Hauptprogramm eine neue, globale Objektvariable starteMethode vom Methodentyp methode_starteFunktion einführen und entsprechend benutzen.

 

Wie man im nachfolgenden Programm microbit_teil_02_prog_20.hex mit dem Quellkode microbit_teil_02_prog_20.js sieht, trifft dies auch auf die lokale Objektvariable „txt_str1“ im Konstrukt basic.forever(() => { … }“ zu:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie man oben im Quellkode sieht, lassen sich sowohl im Hauptprogramm als auch in Konstrukten jederzeit globale und/oder lokale Objektvariablen zur Methodemethode_starteFunktion()“ erstellen und entsprechend nutzen. [ Video 6 ]

 

Aber wie man im Programm microbit_teil_02_prog_21.hex mit dem Quellkode microbit_teil_02_prog_21.js sieht, lässt sich der Methodenaufrufmethode_starteFunktion()“ auch direkt aufrufen, sodass globale und/oder lokale Objektvariablen nicht mehr erforderlich sind:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

[ Video 7 ]

 

Da es im obenstehenden Quellkode noch immer mehrere Displayanzeigen mit dem Statement basic.showString(…)“ gibt, lassen sich diese im Programm microbit_teil_02_prog_22.hex mit dem Quellkode microbit_teil_02_prog_22.js wie folgt zu nur noch einer, wenn auch multifunktionalen Displayanzeige in der Methode methode_starteFunktion = function starteFunktion(str_einlesen: string)“ wie folgt zusammenfassen:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Damit wir ein noch besseres Verständnis von einer Funktion und einer Methode und deren Unterscheidungsmerkmale bekommen, nehmen wir beide gemeinsam in unser Programm microbit_teil_02_prog_23.hex mit dem Quellkode microbit_teil_02_prog_23.js auf:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Damit wir die beiden obenstehenden Programmblöcke

 

·        function starteFunktion(str_einlesen: string) { … }

 

und

 

·        var objektvar_starteMethode
= function
starteMethode(str_einlesen: string) { … }

 

wirklich gut auseinander halten können und es bei der Programmausführung zu keinen Fehlern kommt, sollten Sie unbedingt auf die korrekten Funktions- und Methoden-Namen achten und diese gegebenenfalls abändern. [ Video 8 ]

2.7     Gekapselte Programmmodule in Klassen

Beim Entwickeln und Programmieren ist es zunächst naheliegend, dass man den Programmkode einfach so der Reihe nach, sozusagen Statement für Statement, programmiert und sich freut, wenn alles funktioniert. Das geradlinige, unverzweigte Programmieren ist leicht und bequem führt aber früher oder später dazu, dass das Programm nicht nur umfangreicher, sondern auch komplexer und unübersichtlicher wird.

 

Bei nicht objektorientierten, älteren Programmiersprachen wie z.B. GW-BASIC für MS-DOS von Microsoft  war man dann schon froh, wenn man einzelne Programmteile aus dem Hauptprogramm in sogenannte Unterprogramme (Statement in GW-BASIC: „gosub labelnamereturn“) auslagern konnte, sodass das Hauptprogramm kompakt und übersichtlich blieb. Aber bei vielen Unterprogrammen wurde dann die Programmierung der „gosub“-Unterprogramme irgendwann auch unübersichtlich, sodass es früher oder später nicht ausblieb, dass man einen „return“-Rücksprungbefehl vergaß mit der Folge, dass einfach mit dem nächsten Unterprogramm fortgefahren wurde und es demzufolge zu unvorhersehbaren Effekten bei der Programmausführung kam.

 

Bei Turbo Pascal von Borland ließen sich zusammenhängende Programmteile als sogenannte „include“-Datei auslagern. Bei vielen „include“-Dateien musste man dann aber darauf achten, wie diese voneinander abhängen oder aufeinander aufbauen.

 

Die derzeitigen Programmiersprachen wie z.B. JavaScript, PHP oder Java sind alle objektorientiert und verfügen über Funktionen, Methoden (= Funktion mit Zuordnung zu einer Objektvariablen), Objekten und Klassen.

 

>> Unter einer Klasse (auch Objekttyp genannt) versteht man in der objektorientierten Programmierung ein abstraktes Modell bzw. einen Bauplan für eine Reihe von ähnlichen Objekten.

 

Die Klasse dient als Bauplan für die Abbildung von realen Objekten in Softwareobjekte und beschreibt Attribute (Eigenschaften) und Methoden (Verhaltensweisen) der Objekte. Verallgemeinernd könnte man auch sagen, dass eine Klasse dem Datentyp eines Objekts entspricht. Formal gesehen belegt eine Klasse somit zur Programm-Ausführungszeit keinen Arbeitsspeicher, sondern immer nur die Objekte, die von ihr instanziiert wurden.[Anmerkungen 1]  (…)

 

Vererbung

 

Klassen können miteinander in hierarchischen Beziehungen stehen und zu komplexen Strukturen werden. Die Gesetzmäßigkeiten, nach denen diese gebildet werden, beschreibt das grundlegende Konzept der Vererbung. Hier sind weiterhin die Begriffe Basisklasse und abgeleitete Klasse von Bedeutung, um die Verhältnisse der Klassen untereinander zu charakterisieren. Dabei beschreibt die Basisklasse allgemeine Eigenschaften, ist also eine Verallgemeinerung der abgeleiteten Klassen; diese sind somit Spezialisierungen der Basisklasse.

 

Beispiel: Basisklasse Kraftfahrzeug ist Verallgemeinerung der abgeleiteten Klassen (Spezialisierungen) Auto, LKW, Motorrad und Traktor.

 

Dabei erben die abgeleiteten Klassen alle Eigenschaften und Methoden der Basisklasse (d. h., ein Motorrad hat alle Eigenschaften eines Kraftfahrzeugs, und man kann alles mit ihm machen, das man mit einem Kraftfahrzeug machen kann). Zusätzlich führt die abgeleitete Klasse zusätzliche Eigenschaften und Methoden ein, die bei ihren Objekten möglich sind. (Das Motorrad hat z. B. einen Gepäckträger, ein Auto nicht, dafür aber einen Kofferraum.)

 

Programmierstil

 

In vielen Programmiersprachen ist es üblich, dass der Name einer Klasse mit einem Großbuchstaben beginnt, Variablennamen dagegen mit einem Kleinbuchstaben. << (Quelle: Wikipedia)

 

Durch das Programmieren einer Klasse sind wir schon mitten drin in der objektorientierten Programmierung, obwohl wir noch kein einziges Objekt programmiert haben. Aber das soll uns im Moment nicht weiter stören, geht es doch nachfolgend darum, dass wir zusammengehörende Programmteile in einer Klasse, sozusagen als objektorientiertes Unterprogramm, zusammenfassen.

 

Wie man im Programm microbit_teil_02_prog_24.hex mit dem Quellkode microbit_teil_02_prog_24.js sieht, wurde das Programm „microbit_teil_02_prog_23.hex“ (siehe oben) entkernt, wurden die Funktion starteFunktion(str_einlesen: string) und die Methode var objektvar_starteMethode = function starteMethode(str_einlesen: string) sowie deren Aufrufe im Konstrukt basic.forever(() => { … }) entfernt und die noch leere Klasse class starteKlasse { … } hinzugefügt:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wichtig zu wissen ist an dieser Stelle, dass eine Klasse immer nur dann beim Programmstart des Hauptprogramms oder beim Aufruf von anderer Stelle aus immer nur dann ausgeführt wird, wenn man diese mittels einer Objektvariablen und dem neuen Verweis auf die Klasse z.B. wie folgt aufruft:

 

var objektvar_starteKlasse = new starteKlasse()

 

Wichtig ist ferner, dass sich innerhalb der Klasse kein Programmkode im Sinne von Statements befinden darf! Deshalb dürfen in der Klasse selbst nur Deklarationen und/oder Initialisierungen von Klassen-Variablen stehen.

 

Dies gilt insbesondere auch für Funktionen oder Methoden; diese dürfen ebenfalls nicht in der Klasse selbst „gecodet“ werden!

 

Funktionen und Methoden dürfen nur in einem Konstrukt contructor() { … }“ programmiert, d.h. „gecodet“ werden! Klasse und Konstrukt gehören also stets zusammen!

 

Wenn man wissen will, ob man eine Klasse nebst Konstrukt fehlerfrei programmiert wurde, dann muss man die Klasse mittels des Statements

 

var objektvar_starteKlasse = new starteKlasse()

 

aufrufen, d.h. ausführen:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Da eine Klasse keine Funktion oder Methode ist, lassen sich in ihr nur Deklarationen von Klassen-Variablen vornehmen, die sich aber in allen Funktionen, Methoden usw. innerhalb des Konstruktors constructor() { … }“ initialisieren und anwenden lassen!

 

Dabei dient die this“-Angabe dazu, festzulegen und aufzuzeigen, dass es sich bei der Variablen this.showStringVar um die Klassenvariable showStringVar der Klasse startKlasse() handelt.

 

Man könnte auch sagen, dass es sich bei der this“-Angabe um eine Platzhalter-Variable mit Verweis auf die Klassenvariable showStringVar handelt.

 

Mit dem Programm microbit_teil_02_prog_25.hex und dem Quellkode microbit_teil_02_prog_25.js lässt sich alles nachvollziehen und ausprobieren.

 

Im Zusammenhang mit der Deklaration der Klassenvariablen showStringVar und dem Klassenaufruf, d.h. dem Starten der Klasse starteKlasse() mittels des Statements

 

var objektvar_starteKlasse = new starteKlasse()

 

stellt sich die interessante Frage, ob sich die Klassenvariable showStringVar auch im Hauptprogramm nutzen und mit Inhalten initialisieren lässt, obwohl man ja quasi von außen (= Hauptprogramm) nach innen auf die Klassenvariablen showStringVar zugreift.

 

Da die Klasse starteKlasse() vom Hauptprogramm aus mittels der Variablen objektvar_starteKlasse gestartet wird, lässt sich mittels des Statements wie z.B.

 

txtstr_3 = objektvar_starteKlasse.showStringVar

 

auch auf den Variableninhalt der Klassenvariable showStringVar zu greifen bzw. lässt sich dieser mittels des Statements

 

basic.showString("Ende Quelltext!" + objektvar_starteKlasse.showStringVar)

 

abfragen bzw. im Display wie folgt anzeigen:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Mit dem Programm microbit_teil_02_prog_26.hex und dem Quellkode microbit_teil_02_prog_26.js lässt sich das Ganze nachvollziehen. [ Video 9 ]

 

Wenn man aber der Klassenvariable showStringVar gleich zu Beginn, d.h. zusammen mit dem Start der Klasse starteKlasse() einen Wert mit auf den Weg geben will, dann muss man einen anderen Weg einschlagen und diesen gleich beim Initialisieren der Klasse der Klassenvariable showStringVar wie folgt zuweisen:

 

var objektvar_starteKlasse = new starteKlasse(„Konstrukt!“)   

 

Da der Textstring „Konstrukt!“ direkt an die Klasse starteKlasse übergeben wird, könnte man meinen, dass der Textstring auch von dieser entgegengenommen wird. Dem ist aber nicht so, weil eine Klasse keine Funktion oder Methode ist mit denen sich Werte einlesen lassen. Wie man aber sieht, lassen sich mit dem Konstruktor constructor(str_einlesen: string) { … }“ sehr wohl Daten in Form von Werten oder eines Textstrings einlesen:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie man im Programm microbit_teil_02_prog_27.hex und dem Quellkode microbit_teil_02_prog_27.js sieht bzw. sich auch im Display anzeigen lassen kann, wird am Ende des Quelltextes nur der Text „Ende Quelltext!“ ausgeben. Was aber muss man im Konstruktor constructor(str_einlesen: string) { … }“ noch programmieren, damit am Ende des Quelltextes die vollständige Anzeige „Ende Quelltext! Konstrukt!“ ausgeben wird?

 

Wie man im obenstehenden Screenshot sieht, wurde beim Programm „microbit_teil_02_prog_27.hex“ zwar der Teststring „Konstrukt!“ im Kopf des Konstruktors constructor(str_einlesen: string) { … }“ ordnungsgemäß eingelesen und mittels des Statements basic.showString(str_einlesen)“ auch angezeigt, aber noch nicht an die Klassenvariable showStringVar weitergegeben, sodass sie sich demzufolge auch nicht im Statement basic.showString("Ende Quelltext!" + objektvar_starteKlasse.showStringVar) anzeigen lässt!

 

Wenn wir also erreichen wollen dass am Ende des Quelltextes die vollständige Anzeige „Ende Quelltext! Konstrukt!“ ausgeben wird, dann müssen wir den eingelesenen Variableninhalt „Konstrukt!“ der Variablen str_einlesen noch wie folgt an die Klassenvariable showStringVar weiterreichen:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Bei der Zuweisung des Variableninhalts „Konstrukt!“ von der Variablen str_einlesen an die Klassenvariable this.showStringVar gilt es stets zu beachten, dass diese von rechts nach links erfolgt (siehe Programm microbit_teil_02_prog_28.hex mit dem Quellkode microbit_teil_02_prog_28.js). -

 

Dabei lässt sich die zuvor genannte Zuweisung this.showStringVar = str_einlesen auch direkt ins Statement „basic.showString(this.showStringVar = str_einlesen)“ übernehmen (siehe Programm microbit_teil_02_prog_29.hex mit dem Quellkode microbit_teil_02_prog_29.js):

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

So, nun sind wir so weit, dass wir das obenstehende Programm wieder vervollständigen können, indem wir die Funktion starteFunktion(str_einlesen: string)“ sowie die permanent im Hintergrund laufende Abfrage des Tasters A basic.forever(() => { … }“ wieder ins Programm einbauen:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie man im obenstehenden Screenshot sieht, wurde die Variable str_einlesen im Kopf des Kontruktors contructor(str_einlesen: string) { … } auf lies_parameter_ein abgeändert, um einem eventuellen Konflikt wegen Namensgleichheit aus dem Weg zu gehen. [ Video 10 ]

 

Außerdem wurde der Quellkode für die Displayanzeige

 

basic.clearScreen()

basic.showString(this.showStringVar = str_einlesen)

 

entfernt und durch das Statement

 

this.showStringVar = lies_parameter_ein

 

gleich am Anfang des Kontruktors contructor(lies_parameter_ein: string) { … } ersetzt, um den eingelesenen Parameter lies_parameter_ein mit dem Textstring Konstruktor!“ an die Klassenvariable showStringVar der Klasse starteKlasse zu übergeben.

 

Der Grund dafür ist der, dass der Textstring Konstruktor!“ beim Klassenaufrufvar objektvar_starteKlasse = new starteKlasse("Konstrukt!")“ jetzt nur noch ganz am Ende des Programms mittels des Statements

 

basic.showString("Ende Quelltext!" + objektvar_starteKlasse.showStringVar)

 

angezeigt werden soll (siehe Programm microbit_teil_02_prog_30.hex mit dem Quellkode microbit_teil_02_prog_30.js). -

 

Was jetzt noch fehlt, ist der Einbau der Methode objektvar_starteMethode mit dem Statement

 

var objektvar_starteMethode = function starteMethode(str_einlesen: string) { … }

 

Außerdem müssen wir noch die permanent im Hintergrund laufende Abfrage des Tasters B basic.forever(() => { … }“ wieder ins Programm einbauen:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Mit dem Programm microbit_teil_02_prog_31.hex und dem Quellkode microbit_teil_02_prog_31.js lässt sich das Ganze wie gewohnt ausprobieren und überprüfen. [ Video 11 ]

2.8     Die programmierte Klassengesellschaft

Obwohl wir bezüglich des Programmierens einer Klasse schon eine ganze Menge gelernt haben und inzwischen z.B. wissen, dass sich in einer Klasse selbst wider Erwarten kein Quellkode, sondern stets nur innerhalb eines Konstruktors entwickeln lässt, wissen, dass eine Methode nichts anderes als eine Funktion ist, die an eine Objektvariable gebunden ist und auch wissen, wie man Funktionen und Methoden innerhalb eine Klasse menügesteuert aufruft, gibt es dennoch ein paar Dinge, die es noch zu ergründen gilt.

 

Frage 1

 

Starten Sie zu diesem Zweck das Programm microbit_teil_02_prog_32.hex mit dem Quellkode microbit_teil_02_prog_32.js, und finden Sie heraus, ob, wann und wie die Deklaration

 

new starteKlasse_1("2.) Klasse 1 aufgerufen!")

 

im Hauptprogramm von diesem beim Starten des Programms aufgerufen und ausgeführt wird! [ Video 12 ]

 

Klären Sie diesbezüglich auch weshalb der Textstring „2. Klasse 1 - gestartet!“ beim Aufruf der Deklaration

 

new starteKlasse_1("2.) Klasse 1 aufgerufen!")

 

zwar mit übergeben und bei der Anzeige im Konstrukt

 

„constructor(lies_parameter_ein: string)“

 

auch angezeigt wird, wider Erwarten aber nicht in der Objektvariablen objektvar_starteKlasse_1.showStringVar abgespeichert wird:

 

basic.showString("Ende Quelltext!" + objektvar_starteKlasse_1.showStringVar, 100)

 

[ Video 13 ]

 

Hier geht’s weiter zur Antwort auf Frage 1 mit Video. -

 

So, nun wissen wir, wie man eine Klasse deklariert, nämlich mit dem Statement

 

new starteKlasse_1("1.) Klasse 1 aufgerufen!")

 

und initialisiert, indem man diese der Objektvariablen

 

var objektvar_starteKlasse_1

 

mit dem Statement

 

var objektvar_starteKlasse_1 = new starteKlasse_1("1.) Klasse 1 aufgerufen!")

 

zu ordnet!

 

Ferner wissen wir, dass sich das Konstrukt

 

„constructor(lies_parameter_ein: string)“,

 

das zur bereits deklarierten und initialisierten Objektvariablen der Klasse gehört, jederzeit ein weiteres Mal im Programm durch das Statement

 

new starteKlasse_1()

 

aufrufen und ausführen lässt! -

 

Wir machen uns diese Erkenntnis zu nutze und programmieren eine weitere Klasse, indem wir die Klasse „starteKlasse_1()“ einfach kopieren und diese als Klasse „starteKlasse_2()“ benennen.

 

Dies betrifft dann auch die Funktion „starteFunktion_2()“ und Methode „objektvar_starteMethode_2“, die zwecks besserer Unterscheidung ebenfalls umbenannt wurden, während die Namen der lokalen Variablen der Einfachheit halber unverändert beibehalten wurden.

 

Jetzt wo es zwei, wenn auch hauptsächlich nur namentlich unterschiedliche Klassen gibt, können wir uns auch daran machen und im Hauptprogramm eine entsprechende Menüauswahl programmieren. Da uns aber im Prinzip bzw. wegen der einfachen Bedienbarkeit nur die beiden Taster A und B zur Verfügung stehen, lässt sich mit dem Taster A das Untermenü der Klasse „starteKlasse_1()“ und mit dem Taster B das Untermenü der Klasse „starteKlasse_2()“ aufrufen:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Da wir es jetzt im Programm microbit_teil_02_prog_33.hex mit dem Quellkode microbit_teil_02_prog_33.js mit einem Hauptmenü und in den beiden Klassen jeweils mit einem Untermenü zu tun haben, müssen wir dafür sorgen, dass man jederzeit aus dem Untermenü zurück ins Hauptmenü springen kann. Zu diesem Zweck wurde der boole’sche Schalter menueswitch programmiert, sodass man jederzeit durch Berühren des Sensors „P0“ das Untermenü verlassen kann.

 

Da der berührungsempfindliche Sensor „P0“ zum Verlassen des Untermenüs im Moment leider nur softwaremäßig, d.h. im Browser funktioniert, wurde das Ganze im Programm microbit_teil_02_prog_34.hex mit dem Quellkode microbit_teil_02_prog_34.js noch für die Hardware, d.h. micro:bit“-Rechner mittels des Tasters AB programmiert:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Frage 2

 

Erklären und begründen Sie, weshalb man im Hauptmenü des Hauptprogramms ebenfalls den Menüschalter mit der Variablen menueswitch = false programmieren muss (siehe roter Kosten im obenstehenden Bild).

 

Hier geht’s weiter zur Antwort zur Frage 2 mit Videos. -

 

Wie bereits an anderer Stelle erwähnt, ist es technisch nicht möglich, zwei Tasten wie z.B. die Taster A und B, gleichzeitig zu drücken, da es zwischen beiden Tastendrücken immer einen winzig kleinen Zeitunterschied gibt und der Rechner die Tastendrücke stets hintereinander abfragt, wenn auch sehr schnell, sodass der Anwender nichts merkt.

 

Spätestens beim „gleichzeitigen“ Tastendruck auf die Tasten <Strg>, <Alt> & <Entf> zum Starten des Windows Taskmanagers wird deutlich, dass nur ein gelenkiger Affe alle drei Tasten quasi gleichzeitig drücken kann. Der kundige Windows-Anwender wird natürlich als erstes die Steuerungstaste <Strg> drücken und gedrückt halten! Zweitens die Alternativ-Taste <Alt> und ebenfalls gedrückt halten und drittens auf die Entfern-Taste <Entf> drücken. Diese muss dann aber nur kurz gedrückt werden, sodass sich dann sofort der Windows-Taskmanager startet. Übrigens: Ab Windows 7/10 lässt sich mit dem Windows-Taskmanger leider nicht mehr der Rechner zwangsweise runterfahren, falls sich mal ein Programm aufgehängt hat oder der PC streikt.

 

Da der kleine micro:bit“-Rechner mit dem stromsparenden „ARM Cortex M0“-Prozessor nicht über die absolute Rechenleistung und Rechengeschwindigkeit verfügt, schließlich kostet dieser ja nur so um die 15 Euro, muss man damit rechnen, dass dieser beim „gleichzeitigen“ Betätigen der beiden Taster A&B nicht sofort reagiert, weil er im Hintergrund erst noch eine laufende Anwendung abarbeiten muss. In der Praxis hat sich diesbezüglich herausgestellt, dass es hilfreich ist, wenn man die beiden Taster A&B in rückwärtiger Reihenfolge betätigt. Also erstens den Taster B drücken, gedrückt halten und zweitens gleich darauf den Taster A drücken. Was aber auf jeden Fall klappt, ist, wenn man die beiden Taster A&B in der beschriebenen Weise drückt und dann etwa zwei bis drei Sekunden lang gedrückt hält.

 

Schließlich gilt es zu bedenken, dass es sich bei den beiden Untermenüs in den Klassen „startKlasse_1“ und „startKlasse_2“ um eine while“-Schleife handelt und eben nicht um die im Hintergrund laufende forever“-Routine:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wissen Sie, was ein Computerprogramm ist?

 

>> Ein Computerprogramm oder kurz Programm ist eine den Regeln einer bestimmten Programmiersprache genügende Folge von Anweisungen (bestehend aus Deklarationen und Instruktionen), um bestimmte Funktionen bzw. Aufgaben oder Probleme mithilfe eines Computers zu bearbeiten oder zu lösen. ( … )

 

Ein Computerprogramm gehört zur Software eines Computers. Es liegt meist auf einem Datenträger als ausführbare Programmdatei, häufig im sogenannten Maschinencode vor, die zur Ausführung in den Arbeitsspeicher des Rechners geladen wird. Das Programm wird als Abfolge von Maschinen-, d. h. Prozessorbefehlen von dem oder den Prozessoren des Computers verarbeitet und damit ausgeführt. Unter Computerprogramm wird auch der Quelltext des Programms verstanden, aus dem im Verlauf der Softwareentwicklung der ausführbare Code entsteht.

 

Eine Programmdatei, die aus Maschinencode besteht, enthält Befehle aus dem Sprachschatz des Prozessors, d. h. Befehle, die für den Prozessor „verständlich“ und damit ausführbar sind. Die Erstellung eines solchen Programms bezeichnet man allgemein als Programmierung oder auch als Implementierung. In den Anfängen der Programmierung wurde – bis zur Entwicklung von Programmiersprachen – ausschließlich in Maschinencode programmiert. (Quelle: Wikipedia)

 

Jetzt wissen Sie, dass der Anwender, der mit einem (Computer-) Programm arbeitet, nicht in dieses, d.h. in das Kompilat (= Übersetzung des Quellkode, engl. „source code“, in Maschinen lesbaren Programmkode) schauen kann:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Aber da wir uns ja selbst als Programmierer des micro:bit“-Rechners betätigen, wissen wir natürlich, dass sich nur der Quellkode eines Programms kompilieren, d.h. in Maschinen lesbaren Kode des ARM Cortex M0“-Prozessors übersetzen lässt. Demzufolge ist also der Programmierer/Softwareentwickler der geistige Urheber des Programms, liegen die Rechte des geistigen Eigentums bei diesem. Das ist dann auch der Grund dafür, weshalb man den Quellkode nicht einfach so an Dritte aus der Hand gibt. Diese könnten nämlich den Quellkode verändern, das Programm entsprechend erweitern und als ihr eigenes geistiges Eigentum verkaufen oder selbst vermarkten.

 

Aber selbst wenn der Anwender Einblick in den Quellkode des Programms bekäme, würde er den Quellkode nur dann lesen können, wenn er eine der geläufigen Hochsprachen der Programmierung wie z.B. C/C++, Java, Python, PHP oder JavaScript beherrschen würde. Aber das Lesen von Quellkode heißt nicht automatisch, dass man das Gelesene auch versteht. Das betrifft dann z.B. auch Entwickler, die später einmal den Quellkode von Fehlern beseitigen oder diesen um neue Funktionen erweitern sollen, das Programm aber selbst nicht „geschrieben“ haben. Auch diese müssen sich mühsam in den Spaghetti-Kode des Programms einlesen, diesen studieren und ausprobieren, um zu wissen, wie das Programm denn so tickt. Dabei können die Fehlerbeseitigung und das Erweitern eines Programms extrem teuer werden, insbesondere dann, wenn es zum Programm selbst keine vernünftige Dokumentation des Quellkodes gibt!

 

Weil aber der Anwender mit der Dokumentation des Quellkodes logischerweise nichts anfangen kann, bräuchte dieser eine entsprechende, selbsterklärende Bedienungsanleitung, damit dieser das Programm sofort richtig anwenden und bedienen kann. Eine Bedienungsanleitung ist also auch eine Art Dokumentation des Programms, nur halt für den Anwender!

 

Dabei besteht die Herausforderung beim kleinen micro:bit“-Rechner mit seinem einfachen „5 x 5 Matrix“-LED-Display darin, die Bedienung mittels der beiden Taster A und B möglichst so zu programmieren, dass sich dieser intuitiv bedienen lässt. -

 

Bedienungsanleitung

 

zum Programm „microbit_teil_02_prog_34.hex 
und dem
 Quelltext „microbit_teil_02_prog_34.js

 

1.     Kabelverbindung herstellen

 

Um mit dem micro:bit“-Rechner kommunizieren und das gewünschte Programm auf den Rechner einspielen zu können, muss man zunächst eine entsprechende Verbindung herstellen. Dabei ist es am einfachsten, wenn man ein entsprechendes USB-Kabel verwendet, das mit seinem kleinen USB-2.0-Micro-B-Stecker“ direkt an den micro:bit“-Rechner zwecks Stromversorgung über USB und zum Datenaustausch angeschlossen wird.

 

Der größere USB-2.0-Typ-A-Stecker“ am anderen Ende des Kabels wird an die USB-2.0-Buchse des heimischen Windows-PCs angesteckt.

 

Sobald das USB-Kabel mit dem Windows-PC verbunden wird, erkennt Windows von sich aus, dass ein USB-Gerät angeschlossen wurde, lädt im Hintergrund die entsprechenden Treiber und bindet das USB-Gerät automatisch in das Windows-Dateisystem ein, sodass man ab sofort auf dieses zugreifen kann.

 

ACHTUNG

 

In das Windows-Dateisystem eingebundene USB-Geräte wie z.B. USB-Speichersticks, externe USB-Festplatten oder auch der micro:bit“-Rechner als USB-Gerät müssen nach Gebrauch, d.h. beim Beenden der Arbeit, unter Windows (oder auch Linux oder Android) ordnungsgemäß manuell vom Windows-Dateisystem abgemeldet werden, da es ansonsten beim spontanen Abziehen des USB-Kabels zum Datenverlust kommen kann! -

 

2.     Aufspielen des Programms

 

Damit sich das für den micro:bit“-Rechner entwickelte Programm auf diesem nutzen lässt, muss es zuvor auf das Dateisystem des Rechners aufgespielt werden. Dazu muss zuvor eine entsprechende Verbindung z.B. über das USB-Kabel erfolgreich hergestellt worden sein!

 

Nachdem das gewünschte Programm in das Hauptverzeichnis des micro:bit“-Dateisystems aufgespielt, d.h. kopiert wurde, kann es bis zu 20 Sekunden dauern, bis dieses vom Dateisystem in den Arbeitsspeichers des micro:bit“-Rechners geflasht“, d.h. geladen wurde. Während des Flashens (= Laden in den Arbeitsspeicher) blickt die rückwärtige, gelbe Status-LED des micro:bit“-Rechners. Dabei darf die Datenverbindung und Stromversorung des micro:bit“-Rechners nicht unterbrochen werden, da es ansonsten zu unvorhersehbarem Verhalten bis hin zur Zerstörung des Rechners kommen kann!

 

3.     Starten und Ausführen des Programms

 

Das in den Arbeitsspeichers des micro:bit“-Rechners geflashte Programm wird vom System automatisch gestartet und ausgeführt!

 

Wenn bei dem in den Arbeitsspeicher geladenen Programm nichts anderweitiges programmiert wurde, wie z.B. ein kleiner Begrüßungstext als Laufschrift auf dem „5 x 5 LED-Matrix“-Display, dann bleibt das Display dunkel, sieht man nicht, dass das geladene Programm gestartet wurde! Dies ist auch der Fall, wenn die Laufschrift durchgelaufen ist!

 

Im vorliegenden Fall, d.h. beim Programm „microbit_teil_02_prog_34.hex“, verhält es sich so, dass sich das herunter geladene und in den Arbeitsspeicher geflashte Programm nach etwa 20 Sekunden von allein meldet und im Display die programmierte Laufschrift „Start ...“ anzeigt.

 

Nachdem die Laufschrift durchgelaufen ist, bleibt das Display zwar dunkel, aber das Programm mit den zwei Tastern A, B und A&B (als Kombination von A & B) weiterhin aktiv.

 

4.     Taster A zum Aufrufen des Untermenüs 1

 

Nach dem selbständigen Programmstart befindet sich das Programm im Grundmodus bei dem die beiden Taster A, B und A&B fortwährend auf einen eventuellen Tastendruck hin abgefragt werden.

 

Drückt man nun auf den Taster A, so verzweigt das Programm in das Untermenü 1 mit den beiden Auswahlmöglichkeiten „Menü 1A“ und „Menü 1B“. Dabei wird aber im Display nur die Auswahlmöglichkeit Menue 1A“ angezeigt.

 

Wir befinden uns nun im Untermenü 1.

 

Im Untermenü 1 lässt sich mittels Tastendruck auf den Taster A das Menü 1A und auf den Taster B das Menü 1B aufrufen, sodass im Display die Laufschrift Menue 1A“ oder Menue 1B“ angezeigt wird.

 

Durch den kombinierten Tastendruck auf die beiden Taster A&B für die Zeitdauer von bis zu 5 Sekunden lässt sich das Untermenü 1 wieder verlassen. Dabei erscheint im Display die Laufschrift exit …“, sodass man sich anschließend wieder im Grundmodus befindet.

 

5.     Taster B zum Aufrufen des Untermenüs 2

 

Das Programm befindet sich im Grundmodus bei dem die beiden Taster A, B und A&B fortwährend auf einen eventuellen Tastendruck hin abgefragt werden.

 

Drückt man nun auf den Taster B, so verzweigt das Programm in das Untermenü 2 mit den beiden Auswahlmöglichkeiten „Menü 2A“ und „Menü 2B“. Dabei wird aber im Display nur die Auswahlmöglichkeit Menue 2B“ angezeigt.

 

Wir befinden uns nun im Untermenü 2.

 

Im Untermenü 2 lässt sich mittels Tastendruck auf den Taster A das Menü 2A und auf den Taster B das Menü 2B aufrufen, sodass im Display die Laufschrift Menue 2A“ oder Menue 2B“ angezeigt wird.

 

Durch den kombinierten Tastendruck auf die beiden Taster A&B für die Zeitdauer von bis zu 5 Sekunden lässt sich das Untermenü 2 wieder verlassen. Dabei erscheint im Display die Laufschrift exit …“, sodass man sich anschließend wieder im Grundmodus befindet.

 

6.     Mit dem Kombi-Tastendruck das Untermenü 1 oder 2 verlassen

 

Durch den kombinierten Tastendruck auf die beiden Taster A&B für die Zeitdauer von bis zu 5 Sekunden lässt sich das Untermenü 1 oder 2 wieder verlassen. Dabei erscheint im Display die Laufschrift exit …“, sodass man sich anschließend wieder im Grundmodus befindet.

 

7.     Mit dem Reset“-Taster alles wieder auf Anfang setzen

 

Auf der Rückseite des micro:bit“-Rechners befindet sich ein sogenannter Reset“-Taster mit dem sich der Rechner neu starten lässt. Dabei wird auch das zuvor in den Arbeitsspeicher geflashte Programm wieder neu gestartet, sodass sich dieses wieder im zuvor beschriebenen Grundmodus befindet! -

 

Hier geht’s dann weiter zum micro:bit“-Programmieren, Teil 3

 

 

 

[ Home ] [ zurück ] [ Seitenanfang ] [ Teil 1 ] [ Teil 3 ]