|

Objektorientierte Programmierung
Eine Klasse erweitern
| Objektorientierte
Programmierung |
|
Abstrakt läßt sich schnell erklären,
was man unter objektorientierter Programmierung versteht.
Ein Objekt ist eine Instanz einer Klasse. Eine Klasse wiederum
ist eine Sammlung von Variablen und Methoden. Wer will kann
es auch so sehen: Das Objekt verhält sich zur Klasse,
wie Substantive natürlicher Sprachen zu dem Gegenstand,
den sie bezeichnen. Der einzige Unterschied besteht darin,
dass die einzelnen Deutschen sich unter Tisch (einer Klasse
also) höchst unterschiedliche Dinge vorstellen. Der eine
stellt sich was vor mit drei Beinen, der nächste mit
vier, der übernächste mit fünf, der eine meint,die
Tischplatte ist rund der nächste dreieckig, etc. etc.
etc. Das geht in der Programmierung nicht so ohne weiteres.
Will man die Grundklasse in der Programmierung modifizieren,
muss schon genau festgelegt werden wie. Wer aber zu Ikea geht,
und einen Tisch will, wird vom Verkäufer zu konkreten
Objekten geführt, die alle die Eigenschaft haben, die
die Klasse Tisch hat. Die Tischplatte wird einen gewissen
Abstand zum Boden haben, die Platte wiederum wird auf mehreren
wie auch immer gearteten Pfeilern ruhen, die Tischplatte wird
mehr oder weniger horizontal sein etc. Der langen Rede kurzer
Sinn. Das Konzept der objektorientierten Programmierung ist
trivial. Jedes Substantiv in jeder natürlichen Sprache
ist eine Klasse. Es verweist auf Objekte, die alle Eigenschaften
und Methoden der Klasse haben. Allerdings nur diese. Ein Tisch,
der Personen von A nach B befördert, würde nicht
mehr zur Klasse Tisch gehören, sondern zur Klasse Fahrzeug.
Der schnellste Weg, sich mit der objektorientierten Programmierung
vertraut zu machen, ist ein Programm zu schreiben, dass den
objektorientierten Ansatz nutzt. Das ist jetzt allerdings
nicht mehr so trivial.
<?
class rechner
{
var $a;
var $b;
var $summe;
function setze_werte($c,$d)
{
$this->a=$c;
$this->b=$d;
}
function rechnen()
{
$this->summe=$this->a+$this->b;
return $this->summe;
}
}
$zeiger=new rechner;
$zeiger->setze_werte(40,60);
$ergebnis1=$zeiger->rechnen();
print "Das Ergebnis der ersten Addition ist2".
" <font color=blue>$ergebnis1</font><br>";
$zeiger2=new rechner;
$zeiger2->setze_werte(400,60);
$ergebnis2=$zeiger2->rechnen();
print "Das Ergebnis der ersten Addition ist".
" <font color=blue>$ergebnis2</font><br>";
?>
Wie deutlich sichtbar, definieren wir
eine Klasse. Das heisst wir definieren, um das oben Gesagte
wieder aufzugreifen, ein Substantiv. Die konkreten Objekte,
die wir anschliessend generieren, haben dann alle die Eigenschaften,
die die Klasse hat. Nicht mehr, aber auch nicht weniger. Unsere
Klasse hat drei Variablen nämlich $a, $b und $summe.
Folglich werden alle unsere Objekte auch diese drei Variablen
haben, unabhängig davon, ob wir sie mit Inhalt füllen
oder nicht. Weiter haben wir eine Funktion setze_werte. Die
macht das, was der Name schon sagt. Mit ihr kann man dem Objekt
Werte zuordnen, nämlich $a und $b. So ist da ja auch
mit den Tischen. Dass ein Tisch zum Beispiel eine Farbe hat,
ist klar. Aber niemand geht davon aus, dass alle Tische, die
uns der IKEA Verkäufer zeigt, diesselbe Farben haben
(Im Gegensatz zu Tomaten im übrigen. Da wären wir
echt platt, wenn sie auf einmal lila sind.) Wir definieren
also innerhalb der Klasse, welche Eigenschaften unsere Objekte,
deren Struktur in der Klasse definiert wird, haben. Was uns
wirklich verblüfft ist aber die Syntax der Funktion setze_werte().
Was uns nicht verblüfft ist die Tatsache, dass sie zwei
Parameter übergeben bekomm ($c und $d). Da kennen wir
schon aus dem Kapitel Funktionen . Verblüffend ist das:
$this->a=$c;
$this->b=$d;
Um diese Zeilen zu verstehen, müssen
wir uns erst mal klar machen, dass in dem Beispiel oben zwei
Objekte generiert werden, wobei jedes Objekt eigene Werte
für $a und $b hat. Wir merken dass drastisch an der Tatsache,
dass wir auch zwei verschiedene Ergebnisse erhalten (100 (40
+60) und 460 (400 +60)). Wir rufen also die selbe Klasse auf,
initialisieren die Objekte aber mit unterschiedlichen Werten.
Damit kann man sich schon fast denken, für was das $this
steht. Es steht für das Objekt, mit $this->a=$c weisen
wir also dem aufgerufenen Objekt für die Variable $a
einen Wert zu. Jetzt kann man sich die Frage stellen, wie
das genau funktionniert. In der Zeile
$zeiger=new rechner
bilden wir eine Instanz der Klasse rechner.
Wir bilden also ein Objekt, dass alle Eigenschaften der Klasse
rechner hat. Mit
$zeiger->setze_werte(40,60)
greifen wir auf die Funktion setze_werte()
unseres Objektes zu. Unser Objekt hat die Funktion setze_werte(),
weil ja die Klasse, zu der unser Objekt gehört, diese
Funktion auch hat. Durch die spezielle Syntax mit dem Pfeil,
wird beim Aufruf der Funktion setze_werte der Zeiger auf das
Objekt gleich mitgeliefert. Dieser Zeiger auf das Objekt ist
dann $this. $this und $zeiger verweisen also jeweils auf das
selbe Objekt. Man könnte das Programm auch anders schreiben
und ohne Verwendung von $this direkt auf die Variablen (Eigenschaften)
des Objektes zugreifen. Das macht dann nocheinmal deutlich,
dass $this und $zeiger auf das selbe Objekt verweisen.
<?
CLASS RECHNER
{
VAR $A;
VAR $B;
VAR $SUMME;
FUNCTION RECHNEN()
{
$THIS->summe=$a+$b;
return $this->summe;
}
}
$zeiger=new rechner;
$zeiger->a=40;
$zeiger->b=60;
$ergebnis1=$zeiger->rechnen();
print "Das Ergebnis der ersten Addition ist <FONT
COLOR=BLUE>$ergebnis1</FONT><BR>";
$zeiger2=new rechner;
$zeiger2->a=400;
$zeiger2->b=60;
$ergebnis2=$zeiger2->rechnen();
print "Das Ergebnis der ersten Addition ist <FONT
COLOR=BLUE>$ergebnis2</FONT><BR>";
?>
In diesem Beispiel haben wir uns die
Funktion (Methode) setze_werte() geschenkt. Wir übergeben
die Werte für die Eigenschaften des Objektes direkt.
$zeiger->a=400;
$zeiger->b=60;
Wie deutlich zu erkennen ist, wenn man
das Skript laufen lässt, das Ergebnis genau das gleiche.
Wir übergeben zwar die Werte direkt an das Objekt, holen
es aber mit $this wieder raus. $zeiger und $this verweisen
also auf dasselbe Objekt. Wer bis hierher gelesen hat, dem
ist auch klar, warum dieser Code hier keinerlei Ergebnisse
zeitigt.
<?
CLASS RECHNER
{
VAR $A;
VAR $B;
VAR $SUMME;
FUNCTION RECHNEN()
{
$SUMME=$THIS->a+$this->b;
}
function dividieren()
{
$d=$this->summe/2;
return $d;
}
}
$zeiger=new rechner;
$zeiger->a=40;
$zeiger->b=60;
$zeiger2=new rechner;
$zeiger2->a=400;
$zeiger2->b=60;
$ergebnis1=$zeiger->rechnen();
$ergebnis2=$zeiger2->rechnen();
$ergebnis3=$zeiger->dividieren();
$ergebnis4=$zeiger2->dividieren();
print "Das Endergebnis ist <FONT
COLOR=RED>$ergebnis3</FONT><BR>";
print "Das Endergebnis ist <FONT COLOR=RED>$ergebnis4</FONT><BR>";
?>
Auch hier werden zwar Werte für $a
und $b gesetzt und die Summe dieser beiden Zahlen wird auch
ausgerechnet, aber das Ergebnis wird an $summe übergeben.
Somit ist total unklar, zu welchem konkreten Objekt $summe
gehört und foglich erscheint zweimal 0. Damit es funktionniert,
muss auch das Ergebnis der Addition ebenfalls dem Objekt zugeordnet
werden.
<?
CLASS RECHNER
{
VAR $A;
VAR $B;
VAR $SUMME;
FUNCTION RECHNEN()
{
$THIS->summe=$this->a+$this->b;
}
function dividieren()
{
$d=$this->summe/2;
return $d;
}
}
$zeiger=new rechner;
$zeiger->a=40;
$zeiger->b=60;
$zeiger2=new rechner;
$zeiger2->a=400;
$zeiger2->b=60;
$ergebnis1=$zeiger->rechnen();
$ergebnis2=$zeiger2->rechnen();
$ergebnis3=$zeiger->dividieren();
$ergebnis4=$zeiger2->dividieren();
print "Das Endergebnis ist <FONT
COLOR=RED>$ergebnis3</FONT><BR>";
print "Das Endergebnis ist <FONT COLOR=RED>$ergebnis4</FONT><BR>";
?>
Es ist in der objektorientierten Programmierung
üblich, schon bei der Instanziierung eines Objektes diesem
Werte zuzuweisen. Das geschieht mit Hilfe eines Konstruktors.
Eine Konstruktor ist eine spezielle Methode, die den gleichen
Namen trägt wie die Klasse. Das Beispiel oben könnte
folglich auch so geschrieben werden.
<?
CLASS RECHNER
{
VAR $A;
VAR $B;
VAR $SUMME;
FUNCTION RECHNER($A,$B)
{
$THIS->a=$a;
$this->b=$b;
}
function rechnen()
{
$this->summe=$this->a+$this->b;
}
function dividieren()
{
$d=$this->summe/2;
return $d;
}
}
$zeiger=new rechner(40,60);
$zeiger2=new rechner(400,60);
$ergebnis1=$zeiger->rechnen();
$ergebnis2=$zeiger2->rechnen();
$ergebnis3=$zeiger->dividieren();
$ergebnis4=$zeiger2->dividieren();
print "Das Endergebnis ist <FONT
COLOR=RED>$ergebnis3</FONT><BR>";
print "Das Endergebnis ist <FONT COLOR=RED>$ergebnis4</FONT><BR>";
?>
Wir erhalten wieder das richtige Ergebnis:
Für das erste Objekt 50 (40+60/2) und für das zweite
Objekt 230 (400+60/2).
Wenn eine Klasse, die man braucht, mit einer anderen Klasse
weitgehend identisch ist, aber eine Funktionalität fehlt,
so ist es am günstigsten, man nimmt die eine Klasse und
erweitert sie um die Funktion, die sie noch nicht hat. Unser
Beispiel von oben könnten wir auch anders schreiben.
Anstatt in der Klasse rechner die Funktion dividieren hinzuzufügen,
könnte man auch auch eine neue Klasse schreiben und die
Funktionen aus der Klasse rechner einfach an diese neue Klasse
vererben.
<?
CLASS RECHNER
{
VAR $A;
VAR $B;
VAR $SUMME;
FUNCTION RECHNER($A,$B)
{
$THIS->a=$a;
$this->b=$b;
#print $this->a;
}
function rechnen()
{
$this->summe=$this->a+$this->b;
}
}
class divisio extends rechner
{
function dividieren()
{
$d=$this->summe/2;
return $d;
}
}
$zeiger=new divisio(40,60);
$zeiger2=new divisio(400,60);
$ergebnis1=$zeiger->rechnen();
$ergebnis2=$zeiger2->rechnen();
$ergebnis3=$zeiger->dividieren();
$ergebnis4=$zeiger2->dividieren();
print "Das Endergebnis ist <FONT
COLOR=RED>$ergebnis3</FONT><BR>";
print "Das Endergebnis ist <FONT COLOR=RED>$ergebnis4</FONT><BR>";
?>
Das ist natürlich in so einem kleinem
Beispiel nicht besonders witzig, zeigt aber das Prinzip. Es
würde wenig Sinn machen, eine Funktion, die nur in einem
Spezialfall gebraucht wird, in die Klasse rechner zu schreiben.
In so einem Fall ist es besser, die Basisklasse zu erweitern.
Wie deutlich zu erkennen, hat die Klasse, divisio selbst keinen
Konstruktor. Sie erbt diesen von der Basisklasse, also von
Rechner. Man hätte den Konstruktor auch in die Kindklasse
verlegen können, wie das Beispiel unten zeigt. Allerdings
ist das völlig sinnlos, weil damit die Elternklasse,
die die eigentlich bedeutsame ist, unbrauchbar gemacht wird.
<?
CLASS RECHNER
{
VAR $A;
VAR $B;
VAR $SUMME;
FUNCTION RECHNEN()
{
$THIS->summe=$this->a+$this->b;
}
}
class divisio extends rechner
{
function divisio($a,$b)
{
$this->a=$a;
$this->b=$b;
}
function dividieren()
{
$d=$this->summe/2;
return $d;
}
}
$zeiger=new divisio(40,60);
$zeiger2=new divisio(400,60);
$ergebnis1=$zeiger->rechnen();
$ergebnis2=$zeiger2->rechnen();
$ergebnis3=$zeiger->dividieren();
$ergebnis4=$zeiger2->dividieren();
print "Das Endergebnis ist <FONT
COLOR=RED>$ergebnis3</FONT><BR>";
print "Das Endergebnis ist <FONT COLOR=RED>$ergebnis4</FONT><BR>";
?>
Für ein interessanters Beispiel für
objektorientierte Programmierung siehe Gästebuch:die
objektorientierte Variante
|
 |