# Objekte und Klassen

My guess is that object-oriented programming will be in the 1980s what structured programming was in the 1970s. Everyone will be in favour of it. Every manufacturer will promote his products as supporting it. Every manager will pay lip service to it. Every programmer will practice it (differently). And no one will know just what it is.
T. Rentsch

# Objekte

So wie es die objektorientierte Programmierung in JavaScript gibt, ist sie auch in PHP verfügbar. Objekte sind Datenstrukturen aus Funktionen und Variablen. Die Funktionen werden Methoden und die Variablen werden Eigenschaften genannt. Ein Objekt ist eine Instanz einer Klasse.

Die Implementierung von objektorientierter Programmierung (OOP) ist in PHP jedoch sehr viel genauer und einfach besser als in JavaScript. Obwohl es auch in Perl OOP gibt, werden Sie selten in einem Perl-Script darauf stoßen. Bei PHP-Scripts ist das anders. Dies mag vor allem daran liegen, dass die OOP in PHP sehr einfach umgesetzt wurde und man ohne Probleme schnell und effektiv eigene Klassen programmieren und diese auch einsetzen kann.

# Funktionen

Um jedoch eigene Klassen programmieren zu können, die nicht nur aus Eigenschaften bestehen, werde ich Ihnen nun erklären, wie in PHP eine Funktion definiert wird. Die Definition unterscheidet sich übrigens kaum von der in JavaScript. Mit dem Schlüsselwort function wird die Definition eingeleitet, gefolgt vom Namen der Funktion. Auch wenn Sie an die Funktion keine Parameter übergeben möchten, müssen Sie anschließend zwei runde Klammern notieren. In geschweiften Klammern folgt anschließend der Anweisungsblock der Funktion.

function funktions_name()  
{  
  [Anweisungsblock]  
}

Erlaubte Zeichen für den Funktionsnamen sind alle Buchstaben von a bis z und von A bis Z, die Zahlen von 0 bis 9, der Unterstrich » und Zeichen, deren ASCII-Code im Bereich von 127 bis 255 liegt. Dabei muss das erste Zeichen entweder ein Buchstabe oder der Unterstrich sein. Somit ergeben sich die folgenden erlaubten Funktionsnamen:

eineFunktion     // korrekt, da Buchstabe erstes Zeichen  
eine_funktion    // korrekt, da Unterstrich erlaubt ist  
tötteröö         // korrekt, da ö den ASCII-Code 246 hat  
funktion123      // korrekt, da Zahl nicht erstes Zeichen  
_funktion123_ab  // korrekt, da Unterstrich erlaubt ist

Nicht erlaubt sind hingegen Funktionsnamen wie:

123funktion         // falsch, da Zahl erstes Zeichen  
1_abc               // falsch, da Zahl erstes Zeichen  
abc funktion        // falsch, wegen Leerzeichen  
irgendein-_Name123  // falsch, da Minuszeichen nicht erlaubt

Seit PHP 4 ist es zwar erlaubt, Funktionen an irgendeiner Stelle im Script zu definieren und dann entsprechend darauf zuzugreifen, aber in PHP 3 mussten Funktionen noch definiert werden, bevor im Code darauf zugegriffen werden konnte. Sie sollten aufgrund der Kompatibilität also zuerst die Funktionen definieren und anschließend darauf zugreifen.

Im Anweisungsblock können Sie nun beliebige Anweisungen notieren, Sie müssen aber trotzdem auf die allgemeinen Notationsregeln achten.

<?php

  function drucke()
  {
    echo "Die Funktion drucke wurde aufgerufen!";
  }

  drucke();

?>

Listing 4.1: Eine Funktion in PHP

Die Funktion drucke() gibt bei einem Aufruf einen Text im Browser aus. Auch wenn Sie an eine Funktion keine Parameter übergeben oder keine Parameter erwarten, müssen Sie sowohl bei der Definition als auch beim Aufruf das runde Klammernpaar mit notieren.

Wenn Sie einer Funktion bei ihrem Aufruf einen oder mehrere Parameter übergeben möchten, müssen Sie dies vorher festlegen. Die allgemeine Syntax lautet:

function funktionsname($arg_1, $arg_2, ..., $arg_n)  
{  
  [Anweisungsblock]  
}

Das folgende Beispiel soll dies verdeutlichen:

<?php
  function quadrat_zahl($zahl)
  {
    $quadrat = $zahl * $zahl;
    echo "Das Quadrat von $zahl lautet $quadrat";
  }
  quadrat_zahl(5);
?>

Listing 4.2: Berechnung der Quadratzahl mit einer Funktion

Zuerst wird die Funktion quadrat_zahl() definiert, die eine Zahl als Argument bzw. Parameter erwartet. Innerhalb der Funktion wird das Quadrat dieser Zahl errechnet und im Browser ausgegeben.

Genauso gut könnte die Funktion das Ergebnis der Berechnung auch zurückgeben. Dafür benötigen Sie die Anweisung return. Nach return wird dann die Variable notiert, die zurückgegeben werden soll.

<?php
  function quadrat_zahl($zahl)
  {
    $quadrat = $zahl * $zahl;
    return $quadrat;
  }
  $ergebnis = quadrat_zahl(5);
  echo "Das Qudrat von 5 lautet $ergebnis";
?>

Listing 4.3: Rückgabewert einer Funktion

Bei dem Aufruf der Funktion quadrat_zahl() wird eine Zahl als Parameter übergeben. Die Funktion berechnet nun das Quadrat dieser Zahl und gibt sie mit der Anweisung result zurück. Bei einem Aufruf wird der Rückgabewert mit dem Zuweisungsoperator an die Variable $ergebnis übergeben. Anschließend folgt die Ausgabe dieser Variablen im Browser.

# Klassen

Klassen sind die Basis eines jeden Objekts. Eine Instanz einer Klasse ist also ein Objekt. Der Grundaufbau von Klassen ist sehr einfach.

class klassenname  
{  
  [Variablendeklaration]  
  [Funktionsdeklaration]  
}

Für den Namen einer Klasse gelten die gleichen Regeln wie für Funktionen. Anders als in einem normalen PHP-Script werden die verwendeten Variablen innerhalb einer Klasse zuvor bekannt gemacht. Dies geschieht mit der Anweisung var. Sie definiert eine Variable, ohne diese zwingend mit einem Wert zu versehen. Eine so definierte Variable ist dann später eine Eigenschaft des instanziierten Objekts.

Funktionen innerhalb von Klassen werden ganz normal, wie in Abschnitt 42.2, Funktionen, erklärt, definiert. Sie bilden später die Methoden des instanziierten Objekts.

<?php

  class fahrzeug
  {
    var $hersteller;
    var $typ;
    var $farbe;
    
    function drucke()
    {
      echo "$this->hersteller $this->typ in $this->farbe";
    }
    
    function aendere_farbe($neue_farbe)
    {
      $this->farbe = $neue_farbe;
    }
  }

?>   

Listing 4.4: Eine Klassendefinition in PHP

In Listing 4.4 wird die Klasse fahrzeug definiert. Diese Klasse kennt drei Eigenschaften: $hersteller, $typ und $farbe. Außerdem kennt die Klasse zwei Methoden: drucke() und aendere_farbe().

Die Funktion drucke() soll bei ihrem Aufruf die drei Eigenschaften des Objekts im Browser ausgeben. Dafür wird ein spezielles Objekt namens $this verwendet. Da Sie vorher nie wissen können, wie ein Objekt bezeichnet wurde, müssen Sie das Objekt $this verwenden. Dieses Objekt entspricht immer dem gerade aktuellen und ermöglicht den Zugriff auf alle Eigenschaften und Methoden des aktuellen Objekts. Um auf eine Eigenschaft oder eine Methode zugreifen zu können, folgt nach $this der Operator -> und anschließend entweder der Name der Eigenschaft (ohne das Dollarzeichen $) oder der Name der Methode (inklusive der runden Klammern).

# Objekte instanziieren

Um ein Objekt von einer Klasse ableiten zu können, müssen Sie die Anweisung new verwenden.

$objektname = new klassenname;

Bei der Klasse fahrzeug beispielsweise könnte das Instanziieren einer neuen Klasse folgendermaßen aussehen:

$f = new fahrzeug;

und der Zugriff auf die Eigenschaften und Methoden des Objekts $f so:

$f->hersteller = "Ferrari";  
$f->typ = "F355 Berlinetta";  
$f->farbe = "gelb";  
$f->drucke();

Genau dies wird im folgenden Beispiel demonstriert. Die Klasse fahrzeug wurde in der Datei class_fahrzeug.php definiert.

<?php

  require("class_fahrzeug.php");
  
  $f = new fahrzeug;
  $f->hersteller = "Ferrari";
  $f->typ = "F355 Berlinetta";
  $f->farbe = "gelb";
  $f->drucke();

?>

Listing 4.5: Instanziierung eines Objekts in PHP

Die Ausgabe dieses Beispiels lautet:

Ferrari F355 Berlinetta in gelb

# Konstruktoren

Funktionen, die innerhalb einer Klasse definiert wurden und den gleichen Namen wie die Klasse selbst tragen, werden Konstruktoren genannt. Der Vorteil dieser Konstruktoren ist es, dass sie bei jeder Instanziierung eines Objekts aufgerufen werden. So können Sie schon beim Erzeugen des Objekts z. B. Parameter an ein Objekt übergeben und diese verarbeiten.

Im folgenden Beispiel wurde die Klasse fahrzeug um einen Konstruktor erweitert.

<?php

  class fahrzeug
  {
    var $hersteller;
    var $typ;
    var $farbe;
    
    function fahrzeug($in_hersteller, $in_typ, $in_farbe)
    {
      $this->hersteller = $in_hersteller;
      $this->typ = $in_typ;
      $this->farbe = $in_farbe;
    }
    
    function drucke()
    {
      echo "$this->hersteller $this->typ in $this->farbe";
    }
    
    function aendere_farbe($neue_farbe)
    {
      $this->farbe = $neue_farbe;
    }
  }

?>   

Listing 4.6: Klasse mit Konstruktor

Beim Erzeugen eines neuen Objekts werden nun alle drei Eigenschaften mit initialisiert, indem die einzelnen Werte für die Eigenschaften hinter dem Namen der Klasse notiert werden.

$f = new fahrzeug("Ferrari","F355 Berlinetta","gelb");  
$f->drucke();

Dieser Aufruf würde dann auch die Ausgabe

Ferrari F355 Berlinetta in gelb

erzeugen.

# Vererbungslehre

Sie können neue Klassen von Klassen ableiten. So, wie ein Kind gewisse Eigenschaften von seinen Eltern erbt, erbt dann auch die abgeleitete Klasse die Eigenschaften und Methoden seiner Elternklasse. Der Unterschied: In der OOP haben abgeleitete Klassen nur ein Elternteil. Das Schlüsselwort zum Ableiten einer Klasse lautet extends. Dies wird nach dem Klassennamen notiert, gefolgt von dem Namen der Klasse, von der die neue Klasse abgeleitet werden soll.

An einem Beispiel werde ich Ihnen dies verdeutlichen. Als Elternklasse dient dabei die Klasse person.

class person  
{  
  var $vorname;  
  var $nachname;  

  function drucke()  
  {  
    echo "$this->vorname $this->nachname<br>\n";  
  }  
}

Diese Klasse verfügt lediglich über zwei Eigenschaften: $vorname und $nachname und über eine Methode namens drucke().

Nun wird eine neue Klasse namens kunde definiert, die von der Klasse person abgeleitet wird.

class kunde extends person  
{  
  var $strasse;  
  var $ort;  
  var $kundennr;  

  function kunde($nachname, $vorname)  
  {  
    $this->vorname = $vorname;  
    $this->nachname = $nachname;  
  }  

  function drucke()  
  {  
    echo "$this->kundennr<br>\n";  
    person::drucke();  
    echo "$this->strasse<br>\n";  
    echo "$this->ort";  
  }  
}

Die Klasse kunde verfügt nun sowohl über die beiden Eigenschaften $vorname und $nachname der Klasse person als auch über die Eigenschaften $strasse, $ort und $kundennr. Außerdem verfügt die Klasse kunde über einen Konstruktor, der zwei Eigenschaften initialisiert.

Was aber ist mit der Methode drucke()? Diese wurde in der Klasse person und in der Klasse kunde definiert. Sehen Sie sich die Definition der Methode drucke() in der Klasse kunde genauer an. Zuerst wird die Kundennummer ausgegeben:

echo "$this->kundennr<br>\n";

Danach folgt die Anweisung:

person::drucke().

Die beiden Doppelpunkte :: werden Bereichsauflösungsoperator genannt. Mit ihm können Sie auf die Methode drucke() der Elternklasse zugreifen (person). Sie erkennen also, dass beide drucke()-Methoden koexistieren, nur jeweils in einem anderen Bereich. Die eine Methode existiert in person und die andere in kunde. Durch den Bereichsauflösungsoperator können Sie nun auf die drucke()-Methode der Elternklasse zugreifen, indem Sie zuerst den Namen der Klasse, den Operator :: und zum Schluss den Namen der Methode notieren. Die beiden letzten Zeilen der drucke()-Methode der Klasse kunde geben nun den Rest der Anschrift aus.

# Zusammenfassung

  • Eine Klasse ist eine Sammlung von Variablen und Funktionen, die zusammengefasst werden, ähnlich wie die einzelnen Elemente eines Arrays.
  • Variablen und Funktionen einer Klasse sind Eigenschaften und Methoden eines Objekts.
  • Objekte werden durch die Anweisung new instanziiert.
  • Konstruktoren sind Funktionen, die den gleichen Namen wie die Klasse selbst aufweisen.
  • Mit der Anweisung extends kann eine neue Klasse von einer bereits existierenden Klasse abgeleitet werden. Die neue Klasse erbt dabei alle Eigenschaften und Methoden der Elternklasse.

# Fragen und Übungen

  1. Definieren Sie eine Klasse namens einkaufswagen. Diese Klasse soll eine Variable namens $artikel erhalten. Die Variable soll ein assoziatives Array sein.
  2. Fügen Sie der Klasse eine Funktion mit dem Namen artikel_hinzufuegen hinzu, der zwei Parameter übergeben werden sollen. Der erste soll eine Artikelnummer sein, und der zweite Parameter soll eine Zahl enthalten, die der Anzahl der Artikel entspricht, die hinzugefügt werden. Verwenden Sie die Artikelnummer als Schlüssel und die Anzahl als Wert. Achten Sie darauf, dass ein Artikel mit dieser Artikelnummer bereits vorhanden sein kann und entsprechend erweitert werden muss.
  3. Fügen Sie eine weitere Funktion mit dem Namen artikel_entfernen hinzu, die ebenfalls zwei Parameter übergeben bekommt. Dies sind die Artikelnummer und die Anzahl der Artikel, die entfernt werden sollen. Die Artikelnummer ist wieder der Schlüssel und die Anzahl der Wert. Verringern Sie die Artikelanzahl entsprechend.
  4. Eine weitere Funktion mit dem Namen anzeigen soll nun alle Artikel mit der Artikelnummer und der Anzahl im Browser ausgeben.