Optionen und weiterführende Links



In der Datenbank befinden sich derzeit 477 Specials. Alle Specials anzeigen...

Und jetzt zu etwas ganz anderem

Und jetzt zu etwas ganz anderem

Beim Programmieren gibt es mehrere unterschiedliche Grundansätze. Was Ihr bisher kennengelernt habt, war der prozedurale Ansatz. Dabei sind im Speicher des Computers die Daten einerseits (Variablen) und die Anweisungen andererseits (das eigentliche Programm) zwei getrennte Bereiche. Die Realität ist jedoch etwas anders konstruiert: Wenn Ihr Euch mal umschaut, seht Ihr im wesentlichen Objekte, die Eigenschaften haben und Funktionen ausführen können.

Nehmen wir als Beispiel eine gewöhnliche Lampe. Das ist zunächst mal ein Objekt. Dieses Objekt hat Eigenschaften

  • das Licht ist an oder aus
  • die Birne hat eine bestimmte Stärke (Wattzahl)
  • die Farbe der Glühbirne
  • normale Glühbirne oder Halogenlampe
  • ...

und Funktionen

  • Licht ein- oder ausschalten
  • melden, ob die Glühbirne durchgebrannt ist
  • Glühbirne wechseln
  • ...

Wäre es nicht schön, diese Prinzipien einfach in ein Programm übernehmen zu können?

Variable l sei eine Lampe;
Gebe die Wattzahl von l aus;
wenn (l ist ausgeschaltet)
  schalte l ein;

Genau das ermöglicht die objekt-orientierte Programmierung (OOP).

Lamp l = new Lamp();
print l.strength;
if (!l.isEnlighted())
  l.enlight();

Die allermeisten heutigen Programmiersprachen bieten zumindest objekt-orientierte Ansätze oder sind komplett objekt-orientiert. Das gilt auch für die Sprachen, die wir für dynamische Webseiten brauchen. Daher kann ich Euch zumindest die Grundprinzipien der OOP nicht ersparen.

Die Variable l im obigen Beispiel enthält ein Objekt. Dieses Objekt besitzt Eigenschaften in Form von Variablen. Auf diese Variablen könnt ihr in den meisten Sprachen mit dem Punktoperator zugreifen

// Zugriff auf die Eigenschaft 'strength' des Objekts 'l'
print l.strength;
l.strength = 60; // Neuer Wert für die Eigenschaft

Ebenso besitzt das Objekt Funktionen, die Ihr aufrufen könnt

l.enlight(); // rufe die Funktion 'enlight()' des Objekts 'l' auf

Diese Eigenschaften und Funktionen sind in der jeweiligen Klasse definiert, in diesem Fall in der Klasse 'Lamp'. Die Klasse ist sozusagen das «allgemeine Prinzip 'Lampe'», die Objekte sind die konkreten Lampen, die auf dem Schreibtisch stehen. Ihr könnt Euch die Klasse als Variablen-Typ der Objekte vorstellen. Daher werden Objektvariablen auch mit dem Klassenamen deklariert

// deklariert eine Variable, die ein Objekt
// der Klasse 'Lamp' aufnehmen kann
Lamp l;

Ein neues Objekt müßt Ihr erst erzeugen. Dabei wird, wie bei der Deklaration einer einfachen Variablen, der notwendige Speicherplatz reserviert. Erzeugt wird ein Objekt mit dem Schlüsselwort new

Lamp l; // Deklaration
// erzeuge ein neues Objekt
// der Klasse 'Lamp' in der Variablen l
l = new Lamp();
Lamp ll = new Lamp(); // es geht auch in einer Zeile

Was hinter dem Schlüsselwort 'new' folgt, ist eine besondere Funktion in der Klasse, genannt Konstruktor. Wie bei anderen Funktionen auch, können auch Konstruktoren überladen werden. Das bedeutet, es kann Konstruktoren mit unterschiedlichen Parametern geben

var l = new Lamp(); // Konstruktor ohne Parameter
l = new Lamp(60); // mit 60-Watt-Birne
l = new Lamp(true); // die Lampe ist gleich eingeschaltet
l = new Lamp(60, true); // beides auf einmal

Welche Eigenschaften, Konstruktoren und andere Funktionen die Klassen einer Programmiersprache bieten, steht ebenfalls im Manual. Ihr könnt auch selbst Klassen definieren und benutzen, aber das würde den Rahmen dieses Tutorials sprengen. Wichtig ist nur, daß Ihr die vorhandenen Klassen benutzen könnt, insbesondere bei der clientseitigen Sprache JavaScript.

Objektorientierte Merkwürdigkeiten

Bei der Arbeit mit Objekten müßt Ihr vor allem einen Unterschied zu einfachen Variablen beachten. Das folgende Beispiel soll deutlich machen, was gemeint ist

var a = 0; // erzeuge zwei Variablen
var b = 1;
b = a; // weise b den Wert zu, den a hat
a = 3; // weise a einen neuen Wert zu
print a; // gebe die beiden Werte aus
print b;

Soweit noch nichts sonderlich überraschendes: a hat den Wert 3 und b hat den Wert 0. Aber wenn wir das ganze jetzt mit Objekten machen, sieht es etwas anders aus

Lamp a = new Lamp(60); // erzeuge zwei Objekte
Lamp b = new Lamp(100);
b = a;
a.strength = 90; // setze Eigenschaft neu
print a.strength; // gebe die Eigenschaft der beiden Objekte aus
print b.strength;

Für das Objekt in a wird jetzt 90 ausgegeben, und für das Objekt in b - auch? Wieso das?

Das liegt daran, daß in einer Objektvariablen nicht das Objekt selbst gespeichert wird, sondern nur ein Verweis auf das Objekt. Das bedeutet, durch die Zuweisung 'b = a' verweisen sowohl die Variable a als auch b auf dasselbe Objekt! Dessen Eigenschaft wird mit 'a.strength = 90' neu gesetzt, und dann abgefragt. Und weil eben a und b auf dasselbe Objekt verweisen, wird auch beidesmal dasselbe ausgegeben. Dieses Prinzip ist nicht ganz leicht zu verstehen. Es hilft, wenn Ihr Euch das ganze einfach mal aufmalt

Beispiel mit einfachen Variablen
Beispiel mit einfachen Variablen

Beispiel mit Objekten
Beispiel mit Objekten

Das führt außerdem noch zu einer anderen Merkwürdigkeit: Beim OOP müßt Ihr unterscheiden zwischen Gleichheit und Identität. Zwei Objekte sind gleich, wenn alle Eigenschaften den gleichen Wert haben. Sie sind aber nicht identisch, weil es eben zwei getrennte Objekte sind. Das könnt Ihr Euch vorstellen wie zwei Stück Papier, auf denen der gleiche Text steht. Diese beiden Zettel sind gleich, aber nicht identisch. Der bekannte Vergleichsoperator '==' prüft bei Objekten auf Identität. Zum Test auf Gleichheit kennen viele Klassen eigene Funktionen, z. B. equals() oder compareTo().

Ich hatte vorhin geschrieben, daß alle Eigenschaften und Funktionen zu einem Objekt gehören müssen. Das ist prinzipiell richtig, aber es gibt Ausnahmen. Solche Eigenschaften und Funktionen existieren einmal für die gesamte Klasse. Man nennt sie statische Eigenschaften oder Funktionen.

Statische Eigenschaften oder Funktionen müssen bei der Definition in der Klasse als solche gekennzeichnet sein. Das geschieht meist mit dem Schlüsselwort static. Häfig steht dieses 'static' auch im Manual, um statische Elemente kenntlich zu machen. Verwenden könnt Ihr statische Elemente, indem Ihr statt eines Objekts einfach den Klassennamen angebt. Als Beispiel nehmen wir eine Klasse namens 'Integer', die eine statische Funktion namens 'parseInt(String)' kennt

String in = input(); // hole Eingabe vom User als String
// benutze statische Funktion, um aus dem String ein int zu machen
int i = Integer.parseInt(in);

Ihr braucht also kein Objekt der Klasse Integer, sondern könnt die Funktion «einfach so» benutzen.

Zur OOP gäbe es noch viel mehr zu sagen, aber das würde hier zu weit führen. Daher nur noch ein paar Stichworte

  • Vererbung
  • Polymorphie
  • abstrakte Klassen und Interfaces
  • Geheimnisprinzip und Zugriffsbeschränkungen
  • Fehlerbehandlung und Exceptions
  • Ereignisse und Listener
  • ...

Tips und Tricks

Damit haben wir jetzt endlich das grundsätzliche Rüstzeug, um uns in die Programmierung dynamischer Webseiten zu stürzen. Vorher noch schnell ein paar Tips, die besonders bei der Fehlersuche nützlich sind

Drittel-Prinzip
In vielen Lehrbüchern wird die Entwicklung eines Programms in drei Teile aufgeteilt: Ein Drittel Planung, ein Drittel Programmieren und ein Drittel Fehlersuche. Und für jeden dieser Teile ist etwa gleich viel Zeit zu veranschlagen. Für Euch bedeutet das: Vor dem eigentlichen Code-Schreiben solltet Ihr Euch bereits über eine Reihe von Fragen Gedanken gemacht haben, wie beispielsweise
  • Wo und in welchem Format speichere ich meine Daten?
  • Wie soll mein Programm grundsätzlich aufgebaut sein?
  • Wie soll die Benutzerführung aussehen?
  • ...
Wenn Ihr Euch das während des Code-Schreibens auch noch überlegen müßt, verliert Ihr leicht den Überblick.
Und nach dem Programmieren beginnt das Testen. Dabei solltet Ihr nicht nur «normale» Fälle überprüfen, sondern auch mal absichtlich Fehler machen: Was passiert, wenn ich keine Nummer für das anzuzeigende Bild eingebe? Was passiert, wenn ich ein Bild anfordere, das auf dem Server gar nicht existiert? Was passiert, wenn ich während des Ladens eines Bildes ein neues anfordere? Was passiert, wenn ...?
Bleistift-Test
Gerade bei komplizierteren Codes ist es nicht ganz einfach, logische Fehler zu finden. In solchen Fällen hilft oft der Bleistift-Test. Ihr nehmt einen großen Zettel und vollzieht das Programm Zeile für Zeile nach. Welche Werte haben die Variablen, wie oft werden Schleifen ausgeführt, wie wird an if-Verzweigungen entschieden, ...? Dadurch findet man eigentlich immer zumindest das Problem, häufig läßt die Idee für die Lösung auch nicht lange auf sich warten. Es gibt übrigens auch Programme, mit denen Ihr solche Bleistift-Tests am Rechner machen könnt. Die nennt man Debugger.
'Hier bin ich!'
Eine Variante des Bleistift-Tests ist ein Verfahren, das ich 'Hier bin ich!' nenne. Dabei baut Ihr einfach an wichtigen Stellen kleine Ausgaben ein
print "Jetzt werden die Daten geladen!";
...
print "Jetzt werden die Daten sortiert!";
...
print "Jetzt werden die Daten ausgegeben!";
...
Damit seht Ihr, woran der Rechner jeweils gerade werkelt, und wo es «hängt». Ihr könnt nach dem gleichen Prinzip auch Variablenwerte ausgeben und schauen, ob sie wie gewünscht belegt werden.



Special vom: 16.01.2003
Autor dieses Specials: Henning Kockerbeck
Die weiteren Unterseiten dieses Specials:
Die reine Lehre - HTML
Stilvoll - CSS
Kleiner Grundkurs Programmieren
Jetzt wird's dynamisch - JavaScript
Die andere Seite der Dynamik - PHP
Neue Gefilde - XML
Weiterführende Links
Zurück zur Hauptseite des Specials


?>