Websiteentwicklung: PHP: Eigenschaften

Aus Wikibooks

Eigenschaften[Bearbeiten]

Unsere erste Klasse[Bearbeiten]

Du hast also gesehen, was das Ziel dieses Kapitels ist: Einen sprechenden Baum zu erschaffen. Das mag jetzt nicht besonders nahe an der Wirklichkeit sein, denn sprechende Bäume sieht man eher selten bei Webanwendungen; aber solche anschaulichen Beispiele können OOP am besten vermitteln. Du kannst jetzt also deine allererste Klasse „Baum“ schreiben:

<?php

class Baum {
}

?>

Wie du siehst, fangen alle Klassen mit dem Schlüsselwort class an, gefolgt vom Namen der Klasse (es ist übrigens eine gängige Konvention, Klassennamen groß zu schreiben). Die geschweiften Klammern kennst du ja schon von Bedingungen, Schleifen und Funktionen, hier schließen sie den Inhalt der Klasse ein. Es ist außerdem sinnvoll, für jede Klasse eine eigene PHP-Datei zu erstellen, wie du das auch für einen Satz von Funktionen tun würdest. Speichere diese Klasse also in einer Datei, z.B. mit dem Namen "Baum.php" ab. Willst du jetzt in deiner Seite, z.B. "index.php", auf die Klasse Baum zugreifen, bindest du die Datei mit der Funktion require_once ein:

<?php
require_once 'Baum.php';
?>

require_once (bzw. include_once) stellt im Gegensatz zu require (bzw. include) sicher, dass die Datei nicht aus Versehen zweimal eingebunden wird – das ist sehr wichtig, da Klassen und auch Funktionen nicht doppelt beschrieben werden dürfen.

Jetzt hast du also eine leere Klasse, die dir als Vorlage für Objekte dient, sozusagen ein Baum-Bauplan. Allerdings fehlt dir noch ein Objekt, das wir jetzt erzeugen werden:

Das Schlüsselwort new[Bearbeiten]

Um ein neues Objekt mit einer Klasse als Vorlage zu erzeugen (man nennt das: „eine Instanz der Klasse Baum erzeugen“), verwenden wir das Schlüsselwort new:

<?php
require_once 'Baum.php';

$bar = new Baum();
?>

Wie du siehst, hat die Klasse hier Ähnlichkeiten mit einer Funktion, denn ihr Name wird von Klammern gefolgt. Das liegt daran, dass du mit der Erschaffung des Objektes automatisch den Konstruktor der Klasse aufrufst. Da wir keinen Konstruktor definiert haben, brauchst du keine Parameter übergeben, die Klammern bleiben leer. Um zu prüfen, dass du alles richtig gemacht hast, kannst du dir die Struktur deines bisherigen Objektes mit der Funktion var_dump anzeigen lassen. Ergänze dazu deine "index.php" um folgende Zeile:

var_dump($bar);

Du erhältst diese Ausgabe:

 object(Baum)[1]

Eigenschaften deklarieren[Bearbeiten]

Wie du im Beispielcode im vorherigen Kapitel gesehen hast, besitzt unser Baum zwei Eigenschaften: Er hat eine bestimmte Höhe und Gesundheit. Diese Eigenschaften werden im oberen Teil einer Klasse definiert, ergänze deine Klasse also, dass sie folgende Form annimmt:

<?php

class Baum {

  public $hoehe;
  public $gesundheit;

}

?>

Wenn du deinen bisherigen Code nochmal ausgibst, siehst du diesmal folgende Ausgabe:

 object(Baum)[1]
   public 'hoehe' => null
   public 'gesundheit' => null

Wie erwartet, hat der Baum zwei Eigenschaften, die noch keinen Wert besitzen. Was das Schlüsselwort public zu bedeuten hat, erfährst du unten im Abschnitt Sichtbarkeit.

Du kannst auch bestimmen, dass Standardwerte vergeben werden, z.B. für einen gesunden Keim:

  public $hoehe = 0.1;
  public $gesundheit = 100;

Lass dir das Ergebnis anzeigen, und du wirst sehen, dass alle Objekte dieser Klasse mit diesen Standardwerten starten.

Auf Eigenschaften zugreifen[Bearbeiten]

Jetzt haben wir also einen netten Baum mit Namen $bar, wissen aber eigentlich gar nicht, welche Höhe und Gesundheit er hat (der Weg über var_dump ist gemogelt). Wollen wir jedoch mit dem Baum arbeiten, um z.B. sicherzustellen, dass wir nicht zufällig einen Tisch vor uns haben, müssen wir auf seine Werte zugreifen können. Dies geschieht mit Hilfe des Pfeil-Operators (->, also Bindestrich gefolgt vom größer-als-Zeichen). Ersetze die Ausgabe mit var_dump durch folgenden Code

echo $bar->hoehe;
echo '<br />';
echo $bar->gesundheit;

und du wirst lesen können:

0.1
100

Jetzt ist es leider meistens nicht friedlich in Welten, in denen Bäume sprechen können, und gerade kommt unser Held Foo vorbei, der den Keim mit einem Feind verwechselt und zieht ihm eins mit dem Schwert über. Das ist der Gesundheit unseres kleinen Baumes nicht gerade zuträglich. Um das widerzuspiegeln, greifen wir mit dem Pfeil-Operator auf die Eigenschaft $gesundheit zu und reduzieren diese um 30:

$bar->gesundheit = $bar->gesundheit - 30;

oder in der Kurzschreibweise:

$bar->gesundheit -= 30;

Später werden wir auch ein Objekt des Helden erzeugen, um den Vorgang eines Schlags mit dem Schwert zu realisieren.

Der Typ-Operator instanceof[Bearbeiten]

Die vorige Situation ist dem Helden natürlich echt peinlich, wenn er nicht einmal harmlose Bäume von Feinden unterscheiden kann. Um ihm etwas unter die Arme zu greifen, fragen wir vorher sicherheitshalber nach, ob es sich um ein Objekt der Klasse „Feind“ handelt. Das können wir mit dem Typ-Operator instanceof:

if ($bar instanceof Feind) {
  
  // Feind: angreifen
  $bar->gesundheit = $bar->gesundheit - 30;

} else {
  
  // Freund: guten Tag sagen
  echo 'Seid gegrüßt!';

}

Solange sich also alle Feinde brav an die Regeln halten und sich nicht als Baum verkleiden, sollte dem Helden nicht erneut diese Verwechslung unterlaufen.

Klassenkonstanten[Bearbeiten]

Wie Konstanten, die wir global definieren, haben auch Klassen eigene Konstanten, auf die man zugreifen kann. Sie werden mit dem Schlüsselwort const definiert. Da alle Dinge in unserer Fantasy-Welt reden können (sogar die Tische), erweitern wir unsere Klassendefinition um eine Konstante, die das anzeigt:

<?php

class Baum {

  public $hoehe;
  public $gesundheit;

  const  KANN_REDEN = true;

}

?>

Auf Klassenkonstanten kann man sogar zugreifen, wenn noch nicht mal ein Objekt der Klasse existiert. Das ist allerdings auch logisch, denn Konstanten können, wie der Name schon sagt, nicht verändert werden, daher ist es egal, wie das Objekt beschaffen ist. Außerhalb von Objekten greift man auf Konstanten mit dem Scope Resolution Operator zu (ein doppelter Doppelpunkt). Ersetze deine "index.php" durch folgenden Code:

<?php
require_once 'Baum.php';

if (Baum::KANN_REDEN == true)
{
  echo 'Ja, kann reden.';
} else
{
  echo 'Schweigt sich aus.';
}
?>

Wenn alles stimmt, sollte als Ausgabe "Ja, kann reden." zu sehen sein.

Sichtbarkeit[Bearbeiten]

Nehmen wir einmal an, unser Baum ist ziemlich schüchtern, und möchte nicht, dass wir ihm seinen Gesundheitszustand von außen ansehen können. Er will diese Information nur auf freiwilliger Basis preisgeben. Dies können wir erreichen, indem wir das Schlüsselwort public durch protected ersetzen:

<?php

class Baum {

  public $hoehe;
  protected $gesundheit;

}

?>

Versuchen wir jetzt, uns den Gesundheitszustand des Baumes anzusehen:

<?php
require_once 'Baum.php';

$bar = new Baum();
echo $bar->gesundheit;
?>

PHP wird uns mitteilen, dass wir das nicht dürfen:

 Fatal error: Cannot access protected property Baum::$gesundheit

Das Schlüsselwort protected verhindert also, dass von außen auf diese Eigenschaft der Klasse zugegriffen werden kann. Es ist uns so nicht möglich, die Gesundheit zu lesen, geschweige denn zu schreiben (wir haben es also mit einem unbesiegbaren Baum zu tun). Damit dies wieder möglich wird, müssen wir entsprechende Methoden implementieren. Wie das geht, erfährst du im nächsten Kapitel.

Abschließend noch eine Übersicht über alle drei möglichen Sichtbarkeiten:

Schlüsselwort Wirkung
public Von außen kann auf die Eigenschaft zugegriffen werden.
protected Die Eigenschaft ist von außen nicht sichtbar und kann auch nicht verändert werden.
private Wie protected, allerdings werden Eigenschaften nicht vererbt, können also in abgeleiteten Klassen nicht einmal innerhalb des Objektes gelesen oder geschrieben werden.

Es ist sinnvoll, stets alle Eigenschaften eines Objektes als protected zu deklarieren und nur mit Hilfe von Methoden auf Objekteigenschaften zuzugreifen, selbst wenn diese nichts anderes machen als die Eigenschaft normal zurückzugeben und zu schreiben. Gründe dafür sind u.a.:

  • Du kannst im Nachhinein den Zugriff auf die Eigenschaft einschränken oder Aktionen beim Verändern der Eigenschaft auslösen, ohne den gesamten Code ändern zu müssen
  • In der objektorientierten Programmierung entwirft man Klassen in Hinblick auf Schnittstellen (Interfaces), sodass man die Klasse verwenden kann, ohne ihre konkrete Implementierung zu kennen

In den Beispielen dieses Buches wird allerdings weiterhin direkt auf die Objekteigenschaften zugegriffen, um den Code möglichst gut lesbar zu gestalten.

PHP-Dokumentatiton[Bearbeiten]

Folgende Abschnitte der PHP-Dokumentatition wurden in diesem Kapitel behandelt: