Websiteentwicklung: PHP: Methoden
Methoden
[Bearbeiten]Unsere Klasse Baum hat nun also bestimmte Eigenschaften, auf die wir zugreifen können (je nachdem, welche Sichtbarkeit sie haben). Da der Baum jedoch sprechen soll, braucht er auch die Möglichkeit, irgendetwas zu bewirken. Dies geschieht mithilfe von Methoden: Das sind die Funktionen einer Klasse.
Der Baum beginnt zu sprechen
[Bearbeiten]Wir können unsere Klasse um eine Methode sagHallo erweitern, um den Klassiker aller Programmierbeispiele zu implementieren:
<?php
class Baum {
public $hoehe;
protected $gesundheit;
const KANN_REDEN = true;
public function sagHallo() {
echo 'Hallo Welt!';
}
}
?>
Wenn wir jetzt in unserer Indexseite schreiben
<?php
require_once 'Baum.php';
$bar = new Baum();
$bar->sagHallo();
?>
erhalten wir die erwartete Ausgabe
Hallo Welt!
Wie du nebenbei sicher bemerkt hast, gilt die von Eigenschaften bekannte Sichtbarkeit auch für Methoden.
Statische Eigenschaften und Methoden mit self
[Bearbeiten]Nun wollen wir noch sicherstellen, dass der Baum auch wirklich reden kann. Im letzten Kapitel haben wir die Konstante KANN_REDEN eingebaut, die aussagt, ob die Objekte dieser Klasse sprechen können. Um auf Konstanten in der eigenen Klasse zuzugreifen, können wir das Schlüsselwort self verwenden. Es wird immer dann angewendet, wenn man auf Elemente einer Klasse zugreifen will, für die kein Objekt benötigt wird. Erweitere die Methode sagHallo also folgendermaßen:
public function sagHallo() {
if (self::KANN_REDEN == true) {
echo 'Hallo Welt!';
return true; // zurückgeben, dass der Sprechversuch geklappt hat
} else {
return false; // Der Baum kann gar nicht reden
}
}
Die Ausgabe bleibt gleich, da der Baum reden kann.
Objekteigenschaften und -methoden mit $this
[Bearbeiten]Allerdings wollten wir doch die Gesundheit des Baumes anzeigen lassen, und zwar wie im Einführungsbeispiel als praktischen Text. Um auf Eigenschaften und Methoden zuzugreifen, während man sich innerhalb eines Objektes befindet, verwenden wir die Pseudovariable $this. Um also den Baum mitteilen zu lassen, wie es ihm geht, fügen wir die Methode sage_mir_dein_wohlbefinden in die Klasse Baum ein:
class Baum {
public $hoehe;
protected $gesundheit;
const KANN_REDEN = true;
public function sagHallo() {
if (self::KANN_REDEN == true) {
echo 'Hallo Welt!';
return true; // zurückgeben, dass der Sprechversuch geklappt hat
} else {
return false; // Der Baum kann gar nicht reden
}
}
public function sage_mir_dein_wohlbefinden() {
if ( $this->gesundheit > 80 ) return 'Mir geht es super.';
if ( $this->gesundheit > 40 ) return 'Ich hatte schon bessere Tage.';
if ( $this->gesundheit > 0 ) return 'Mir geht es echt mies.';
return 'Ich bin ein Tisch.'; /* tritt nur ein wenn $this->gesundheit
* kleiner oder gleich 0 ist. */
}
}
Wie du siehst, greift die Methode mit $this auf ihre eigene Eigenschaft zu. Wenn du jetzt wissen willst, wie es dem Baum geht
echo $bar->sage_mir_dein_wohlbefinden();
erhältst du die Ausgabe:
Ich bin ein Tisch.
Klar, denn wir haben keinen Standardwert definiert, der Baum hat also eine Gesundheit von null (was nicht exakt das Gleiche ist wie 0). Um dem armen Tisch zu helfen, fügen wir noch die Methode veraendereGesundheit hinzu, um die Eigenschaft Gesundheit zu verändern.
public function veraendereGesundheit($wert) {
$this->gesundheit += $wert;
// Die Gesundheit soll nur von 0 bis 100 gehen
if ($this->gesundheit < 0) {
$this->gesundheit = 0;
} elseif ($this->gesundheit > 100) {
$this->gesundheit = 100;
}
}
Parameter funktionieren hier genauso wie bei Funktionen. Wir können jetzt testweise die Gesundheit erhöhen und senken:
<?php
require_once 'Baum.php';
$bar = new Baum();
$bar->veraendereGesundheit(30); // Gesundheit = 30
echo $bar->sage_mir_dein_wohlbefinden();
echo '<br />';
$bar->veraendereGesundheit(30); // Gesundheit = 60
echo $bar->sage_mir_dein_wohlbefinden();
echo '<br />';
$bar->veraendereGesundheit(30); // Gesundheit = 90
echo $bar->sage_mir_dein_wohlbefinden();
echo '<br />';
$bar->veraendereGesundheit(-100); // Gesundheit = 0
echo $bar->sage_mir_dein_wohlbefinden();
?>
Ausgabe:
Mir geht es echt mies. Ich hatte schon bessere Tage. Mir geht es super. Ich bin ein Tisch.
Somit macht das Objekt eine wunderbare Verwandlung vom Tisch zum selbstbewussten Baum und wieder zurück durch.
Objekte als Referenz – neue Funktion von PHP 5
[Bearbeiten]Eine tolle Neuerung von PHP 5 ist, dass Objekte standardmäßig immer als Referenz weitergegeben werden. Was bedeutet das? Nehmen wir an, wir haben eine Klasse Welt, die exakt einen Baum enthalten kann (es handelt sich um eine sehr, sehr kleine Welt). Hier ist die Definition der Klasse:
<?php
class Welt {
protected $baum;
public function pflanzeBaum($baum) {
$this->baum = $baum;
}
public function setzeBaumhoehe() {
$this->baum->hoehe = 10;
}
}
?>
Führen wir nun in der Indexseite diesen Code aus:
<?php
require_once 'Baum.php';
require_once 'Welt.php';
$bar = new Baum();
$welt = new Welt();
$bar->hoehe = 5;
echo $bar->hoehe;
echo '<br />';
$welt->pflanzeBaum($bar);
$welt->setzeBaumhoehe();
echo $bar->hoehe;
?>
Als Ergebnis erhalten wir
5 10
Das liegt daran, dass keine Kopie des Objekts gepflanzt wurde, sondern das Objekt selbst als Referenz übergeben wird. Das ist meistens sowieso das gewünschte Ergebnis, schließlich handelt es sich um den selben Baum, den wir in die Welt einpflanzen. Auch der Zuweisungsoperator = wird immer nur eine Referenz des Objekts zurückgeben. Wünschen wir aber eine Kopie, können wir das Schlüsselwort clone verwenden:
$ber = clone $bar;
Type Hinting
[Bearbeiten]Spielen wir doch einmal Matrjoschka (auch als russische Puppe bekannt) und pflanzen wir anstatt des Baumes eine Welt in eine Welt:
<?php
require_once 'Baum.php';
require_once 'Welt.php';
$welt = new Welt();
$welt2 = new Welt();
$welt->pflanzeBaum($welt2);
$welt->setzeBaumhoehe();
echo $welt2->hoehe;
?>
Eigentlich erwarten wir eine Fehlermeldung, denn schließlich handelt es sich um eine Welt und keinen Baum. Eine Welt hat doch keine „Baumhöhe“! Zur Überraschung liefert uns PHP aber seelenruhig die Ausgabe
10
als ob es sich um einen Baum handeln würde. Das liegt daran, dass Eigenschaften, die in Klassen nicht definiert sind (hier die Eigenschaft $hoehe in der Klasse Welt) als sogenannte Magic Properties zur Laufzeit erzeugt werden. Die Welt hat jetzt eine Eigenschaft $hoehe, wie uns var_dump($welt2) auch zeigt:
object(Welt)[2] protected 'baum' => null public 'hoehe' => int 10
Wie können wir also verhindern, dass die Welt stur jedes Objekt einpflanzt? Die Antwort lautet Type Hinting. Wir sagen bei Angabe der Parameter in der Methode, die Instanz welcher Klasse das Objekt sein soll:
public function pflanzeBaum(Baum $baum) {
$this->baum = $baum;
}
Wenn wir jetzt den Code ausführen, erhalten wir die gewünschte Fehlermeldung:
Catchable fatal error: Argument 1 passed to Welt::pflanzeBaum() must be an instance of Baum, instance of Welt given
Type Hinting funktioniert übrigens auch unter Angabe von Interfaces.
PHP-Dokumentation
[Bearbeiten]Folgende Abschnitte der PHP-Dokumentation wurden in diesem Kapitel behandelt: