„Nichts ist schwieriger als das Vereinfachen. Nichts ist einfacher als das Komplizieren.“
Georges Elgozy ( Politiker und Autor, 1909-1989)
Ausgewählte Basiskonzepte der Objektorientierung sollen hier kurz umrissen werden. Sie müssen diesen Teil nicht unbedingt lesen, um das Tutorial nachzuvollziehen. Es lohnt jedoch in jedem Falle, sich intensiver mit dieser Problematik zu beschäftigen. Zum objektorientierten Paradigma zählen folgende Konzepte:
lat. abstractus „abgezogen“, von abs-trahere „abziehen, entfernen, trennen“ Bedeutung: von der Gegenständlichkeit losgelöst
Nicht erschrecken. Die Herleitung des Begriffs ist wichtig. Verweilen Sie einen Moment bei dem Gedanken: „von der Gegenständlichkeit losgelöst“. Das bedeutet nichts anderes, als das wir in der Lage sind, mit etwas umzugehen, ohne dass es da sein muss. Frauen reden über Männer sogar am eifrigsten, wenn diese nicht anwesend sind! Und damit haben wir auch schon den Bogen zur Sprache geschlagen. Sprache ist Ausdruck der uns von Natur aus gegebenen Fähigkeit zu abstrahieren. Das Gegenständliche bilden wir in Begriffen ab. Und mehr soll an dieser Stelle dazu auch nicht gesagt werden.
Wir geben den Dingen Namen.
Womit wir beim nächsten Punkt sind. Dinge bezeichnet der Fachmann als Objekte und mal ehrlich, Dingorientierung klingt auch nicht wirklich sexy. Also dann doch lieber Objektorientierung. Objekte, das sind die Bausteine, aus denen die Systeme, welche wir programmieren wollen, bestehen. Für uns sind das zum Beispiel der ARM-Controller, vielleicht ein Taster und eine LED usw.. Diese Objekte besitzen konkrete Eigenschaften und typisches Verhalten. Der Controller hat eine bestimmte Speicherkapazität, der Taster prellt etwas und die LED leuchtet grün. Die Eigenschaften bilden wir in Programmen als Variablen (Attribute) und das Verhalten als Funktionen (auch Methoden bzw. Operationen genannt) ab. Programmieren wir objektorientiert, müssen wir dafür sorgen, dass auch das Programm aus genau diesen Objekten besteht und die Attribute und Operationen diesen Objekten zugeordnet sind.
Die Bausteine, aus denen das System besteht, sind der Ausgangspunkt der Softwareentwicklung. Diese Bausteine bezeichnen wir als Objekte.
Der Name, welchen wir für ein Ding benutzen, bezeichnet meist nicht nur das einzelne Ding, sondern eine Menge (Gruppe) gleichartiger Dinge. Nehmen wir zum Beispiel den Taster. Davon haben wir auf unserem Experimentierboard schon mal drei Stück. Um diese zu unterscheiden, geben wir jedem noch einen individuellen Namen, nämlich Taster-1, Taster-2 und Taster_3. Taster steht also als Begriff für alle Schalter mit den entsprechenden gleichen Eigenschaften. Der Fachmann bezeichnet so etwas als Kategorie oder auch als Klasse. Die Objekte Taster-1 bis Taster-3 sind Bausteine unseres Systems und gehören zur Klasse (Gruppe) der Taster. Unser oberschlauer Fachmann bezeichnet diese beiden konkreten Objekte auch gern als Instanzen der Klasse Taster. Übrigens kennen wir diese Problematik schon aus der klassischen Programmierung in Form von Typen und Variablen. Klassen sind die Typen und die Objekte so etwas wie die Variablen.
Wir geben einer Menge gleichartiger Bausteinen einen Gruppennamen (Klassennamen) und beschreiben die gemeinsamen Merkmale (Attribute und Operationen). Objekte sind Instanzen einer Klasse.
Taster haben mit DIP-Schaltern und Bausteinen der 74er Reihe etwas gemeinsam, sie liefern digitale Signale. Wesentliche Aspekte der Programmierung für Ein- und Ausgaben sind bei all diesen Bausteinen gleich. In der objektorientierten Systementwicklung ist man bestrebt, gemeinsame Merkmale (Attribute und Operationen) nur einmal zu programmieren, um Arbeitsaufwand zu sparen. Das einmal programmierte Merkmal soll aber in allen Bausteinen wiederverwendet werden. Dazu benutzt man den Mechanismus der Vererbung. Das bedeutet, man muss eine allgemeingültige Basisklasse schaffen und dort die gemeinsamen Merkmale programmieren. Das könnte für die oben genannten Bausteine zum Beispiel die Klasse Digital_Baustein sein. Das für einen Taster noch einen PullUp benötigt wird, ist etwas Spezielles und gehört nicht zu den gemeinsamen Merkmalen. Ein solches spezielles Merkmal wird dann auch nicht in der Basisklasse Digital_Baustein, sondern in einer speziellen Klasse, die zum Beispiel eben genau Taster oder wer es denglisch mag PushButton heißen könnte, programmiert. Jedoch die Masse an Merkmalen erbt der Taster von seiner Basisklasse. Diese spezialisierten Klassen nennt der Fachmann auch Ableitungen. Umgangssprachlich lässt sich Vererbung mit „ist ein/ist eine“ ausdrücken.
Basisklassen sind oft schon vorhanden und enthalten häufig benötigte Merkmale. Diese zu benutzen (von diesen zu erben), spart Programmieraufwand.
Besonders dann, wenn der Benutzer einer Klasse nicht deren Entwickler ist, kann es wichtig sein, bestimmte interne Sachverhalte der Klasse vor versehentlich falscher Benutzung zu schützen. Dafür kennt die Objektorientierung das Konzept der Sichtbarkeit. Attributen und Operationen können zum Schutz vor unsachgemäßem Zugriff unterschiedliche Sichtbarkeiten zugewiesen werden. Man unterscheidet in der Theorie zwischen den Sichtbarkeiten public, package, protected und privat. Für den Anfang wollen wir erst einmal nur die Sichtbarkeiten public und protected unterscheiden. Wie deren Namen bereits verdeutlichen, heißt public (öffentlich), dass von außen zugegriffen werden darf und protected (geschützt), das der Zugriff nicht erlaubt ist.
Objekte können zum Schutz bestimmte Merkmale (vor allem Eigenschaften, aber auch Verhalten) verbergen.
Um Komplexität zu beherrschen, kann man größere Dinge aus kleineren zusammenbauen. Dabei ist das Ganze verantwortlich für seine Einzelteile. Das ist nicht nur beim Programmieren so. Es verwundert also nicht, dass in einer objektorientierten Programmiersprache komplexe Klassen aus einfachen zusammengebaut werden können. Die Verantwortlichkeit kann man vereinfacht mit hat ausdrücken.
Komplexe Systeme bestehen aus einfachen Bausteinen.
Das Konzept der Nachrichten müssen wir aus zwei Blickwinkeln betrachten. Zum einen im Zusammenhang mit der oben genannten Kapselung. Es hat sich bewährt, vor allem Attribute vor dem direkten Zugriff zu schützen und das Schreiben oder Lesen von Attributen nur über den Aufruf von Operationen zu ermöglichen. Dieser Aufruf von Operationen bedeutet, dem betreffenden Objekt eine Nachricht zu senden. Das Objekt kann auf die Nachricht antworten; diese Antwort ist dann der Rückgabewert der Operation. Somit kommuniziert also das System mit seinen Bausteinen über diese Nachrichten. Das der Aufruf von Operationen Nachricht und nicht Befehl genannt wird (obwohl er aussieht wie der Befehl in einer klassischen Programmiersprache), soll ausdrücken, dass der Empfänger entscheidet, was auf die Nachricht hin getan wird. So kann es durchaus sein, dass das System dem Objekt Seitenfenster_links zwar die Nachricht schließen sendet, dieses aber nicht darauf reagiert. Solch ein Verhalten muss kein Programmierfehler sein. Das Objekt Seitenfenster_links kann zum Beispiel über die Messung des Motorstroms eine Blockade festgestellt haben und entscheidet für sich selbst, zur Sicherheit den Motor abzuschalten, ohne erst mal um Genehmigung zu bitten.
Das System arbeitet mit seinen Bausteinen zusammen, indem es mit diesen Nachrichten austauscht.
Manchmal ist es erforderlich, das Einzelteile direkt miteinander Nachrichten austauschen. Der kleine Dienstweg sozusagen. Dabei besteht ein wesentlicher Unterschied zur Aggregation, die Einzelteile sind nicht füreinander verantwortlich, kennen sich aber.
Bausteine können mit anderen Bausteinen in Beziehung stehen. Man kennt sich.
Unsere natürliche Sprache ist objektorientiert!
Wenn der Taster gedrückt ist schalte die LED an. If the button is pressed the LED will turn on. if button.isPressed then led.on if ( button.isPressed() ) led.on();