PHP-Lektionen – Lektion 13 – Grundlagen der OOP (objektorientierte Programmierung)
In den vorherigen Lektionen habe ich bereits über folgende PHP-Datentypen geschrieben: boolean, integer, float, string, Arrays. In dieser Lektion erzähle ich über einen weiteren in PHP verfügbaren Datentyp – das Objekt.
Objekte ähneln Arrays, sie können verschiedene Datentypen enthalten, genau wie Arrays: Zahlen, Texte, Arrays und sogar andere Objekte.
Objekte können wie Arrays andere Datentypen enthalten. Diese Daten nennen wir dann Eigenschaften (Felder) des Objekts. Außerdem können Objekte Funktionen in sich selbst enthalten, diese Funktionen nennen wir Methoden.
Aber Objekte haben zwei große Unterschiede zu Arrays:
1. Objekte können Methoden enthalten.
Methoden sind Funktionen, die im Namen eines Objekts aufgerufen werden. Die Bindung von Funktionen an Objekte ermöglicht es zu definieren, welche Operationen ein Objekt ausführt und welche Operationen auf einem Objekt durchgeführt werden können.
2. Objekte werden aus Klassen erstellt.
Bevor wir ein Objekt erstellen, müssen wir eine Klasse definieren. In der Klasse beschreiben wir, welche Felder und Methoden das Objekt haben wird. Das definiert die Struktur von Objekten und erleichtert das Verständnis darüber, welche Daten ein Objekt speichern soll und welche Operationen es ausführen kann. Beim Erstellen eines Objekts aus einer Klasse können wir das Objekt mit Anfangsdaten füllen, sodass alle neu erstellten Objekte nicht leer sind.
Objekte sind wohl der bequemste Container zur Speicherung von Daten. Objekte in PHP helfen, reale Weltobjekte zu modellieren, zum Beispiel haben wir eine Datenbank mit Informationen über Bücher. Ein Buch hat einen Autor, Seitenanzahl, Verlag, Auflagennummer, Rezension, typografische Daten. Zur einfachen Datenverarbeitung gruppieren wir diese in der Klasse Buch, die Eigenschaften (Felder) Autor, Seitenanzahl, Verlag, Auflagennummer, Rezension, typografische Daten usw. enthält. So erstellen wir Objekte, die echten Büchern ähneln. Das ist besonders praktisch, weil die Daten unserer Websites in Tabellen mit Feldern gespeichert werden, so können wir die Tabellennamen als Klassen und die Tabellenfelder als Eigenschaftsnamen verwenden. Das macht die Arbeit mit Daten deutlich einfacher.
Wir werden später anhand von Beispielen den Unterschied zwischen Arrays und Objekten genauer betrachten.
Möglichkeiten von PHP 5.2 und höher:
Fangen wir an mit der Definition einer Klasse für unsere Objekte. Beachten Sie, dass Klasse im Singular steht und Objekte im Plural – damit lenke ich Ihre Aufmerksamkeit darauf, dass man aus einer Klasse viele Objekte erstellen kann:
<?php class book{ } ?>
Mit dem Wort class definieren wir eine Klasse für zukünftige Objekte. Jetzt erstellen wir Objekte:
<?php class book{ } $book1 = new book; $book2 = new book; print_r($book1); print_r($book2); ?>
Mit dem Schlüsselwort new erstellen wir neue Objekte der Klasse book. Jedes Objekt einer Klasse nennen wir Instanz der Klasse. So haben wir zwei Instanzen der Klasse book, nämlich $book1 und $book2. Zusätzlich haben wir print_r-Funktionen eingefügt, um den Inhalt der Variablen $book1 und $book2 auf dem Bildschirm anzuzeigen:
PHP zeigt an, aus welcher Klasse das Objekt stammt. Wären Daten im Objekt enthalten, würden diese ebenfalls angezeigt. Jetzt fügen wir solche Daten hinzu. Zuerst müssen wir Eigenschaften der Klasse definieren. Ab PHP 5.2 werden Eigenschaften mit drei Schlüsselwörtern definiert: public, protected, private (es wird auch noch die alte Schreibweise var unterstützt, dazu später mehr). Wer mit Delphi oder C++ gearbeitet hat, wird diese Schlüsselwörter kennen, da sie dort genau gleich funktionieren.
public – definiert öffentliche Eigenschaften und Methoden der Klasse. Auf diese Eigenschaften kann man nach Erstellung des Objekts zugreifen. Wir verwenden public für die Buchdaten-Eigenschaften.
protected – definiert geschützte Eigenschaften und Methoden. Diese sind nur innerhalb der Klasse selbst und in vererbten (Kind-)Klassen aufrufbar. Ein Aufruf von außen führt zu einem Fehler. Wir behandeln protected später bei Vererbung.
private – definiert private Eigenschaften und Methoden. Diese sind nur innerhalb der Klasse aufrufbar, selbst Kindklassen können nicht darauf zugreifen.
Fürs Erste verwenden wir public für alle Eigenschaften und Methoden.
class book{ public $author; public $numberOfPages; public $year; public $publishingOffice; public $editionNumber; }
Nun haben wir Eigenschaften in der Klasse, womit wir in Instanzen auf die Eigenschaften zugreifen können:
class book{ public $author; public $numberOfPages; public $year; public $publishingOffice; public $editionNumber; } $book1 = new book; $book1->author = 'Abramenko I.A'; $book1->numberOfPages = 192; $book1->year = 2013; $book1->publishingOffice = 'Moscow'; $book1->editionNumber = 1; $book2 = new book; print '<pre>'; print_r($book1); print_r($book2); print '</pre>';
Ergebnis: Ein ausgefülltes und ein leeres Objekt:
Jetzt wissen Sie, wie Sie Daten in Objekte schreiben. Nun zu Methoden. Wie erwähnt sind Methoden Funktionen, die über das Objekt aufgerufen werden. Wir fügen Ausgabemethoden für jede Eigenschaft hinzu:
<?php class book{ public $author; public $numberOfPages; public $year; public $publishingOffice; public $editionNumber; public function getAuthor(){ return $this->author; } public function getNumberOfPages(){ return $this->numberOfPages; } public function getYear(){ return $this->year; } public function getPublishingOffice(){ return $this->publishingOffice; } public function getEditionNumber(){ return $this->editionNumber; } } $book1 = new book; $book1->author = 'Abramenko I.A'; $book1->numberOfPages = 192; $book1->year = 2013; $book1->publishingOffice = 'Moscow'; $book1->editionNumber = 1; $book2 = new book; print '<pre>'; print $book1->getAuthor() . '<br />'; print $book1->getNumberOfPages() . '<br />'; print $book1->getYear() . '<br />'; print $book1->getPublishingOffice() . '<br />'; print $book1->getEditionNumber() . '<br />'; print '</pre>'; ?>
So greifen wir auf Objekte mittels Methoden statt direkt auf Eigenschaften zu. Beachten Sie die Variable $this. Sie steht für die aktuellen Instanzwerte des Objekts. Für $book1 ist $this innerhalb der Klasse mit den Werten von $book1 identisch. Außerhalb der Klasse funktioniert $this nicht. Nun fügen wir noch zwei Methoden hinzu, um das Buch in Tabelle oder div darzustellen:
class book{ public $author; public $numberOfPages; public $year; public $publishingOffice; public $editionNumber; public function getAuthor(){ return $this->author; } public function getNumberOfPages(){ return $this->numberOfPages; } public function getYear(){ return $this->year; } public function getPublishingOffice(){ return $this->publishingOffice; } public function getEditionNumber(){ return $this->editionNumber; } public function displayTable(){ $content = '<table style="border: 1px solid #000">'; $content .= '<tr><td>Author</td><td>'. $this->getAuthor() . '</td></tr>'; $content .= '<tr><td>Number of pages</td><td>'. $this->getNumberOfPages() . '</td></tr>'; $content .= '<tr><td>Year</td><td>'. $this->getYear() . '</td></tr>'; $content .= '<tr><td>Publishing office</td><td>'. $this->getPublishingOffice() . '</td></tr>'; $content .= '<tr><td>Edition number</td><td>'. $this->getEditionNumber() . '</td></tr>'; $content .= '</table>'; return $content; } public function displayUnformatted(){ $content = '<div style="border:1px solid #ddd">'; $content .= '<label>Author:</label><div>'. $this->getAuthor() . '</div>'; $content .= '<label>Number of pages:</label><div>'. $this->getNumberOfPages() . '</div>'; $content .= '<label>Year:</label><div>'. $this->getYear() . '</div>'; $content .= '<label>Publishing office:</label><div>'. $this->getPublishingOffice() . '</div>'; $content .= '<label>Edition number:</label><div>'. $this->getEditionNumber() . '</div>'; $content .= '</div>'; return $content; } } $book1 = new book; $book1->author = 'Abramenko I.A'; $book1->numberOfPages = 192; $book1->year = 2013; $book1->publishingOffice = 'Moscow'; $book1->editionNumber = 1; $book2 = new book; $book2->author = 'Leshkina S.O.'; $book2->numberOfPages = 200; $book2->year = 2013; $book2->publishinOffice = 'Moscow'; $book2->editionNumber = 1; print $book1->displayTable(); print $book2->displayUnformatted();
Unser Code ist schon ziemlich umfangreich, aber gut lesbar. Ich habe ganz vergessen, den Buchtitel hinzuzufügen, fügen wir also noch das Feld name und entsprechende Methoden hinzu:
<?php class book{ public $author; public $name; // arghh, ich habe es vergessen. public $numberOfPages; public $year; public $publishingOffice; public $editionNumber; public function getAuthor(){ return $this->author; } public function getName(){ return $this->name; } public function getNumberOfPages(){ return $this->numberOfPages; } public function getYear(){ return $this->year; } public function getPublishingOffice(){ return $this->publishingOffice; } public function getEditionNumber(){ return $this->editionNumber; } public function displayTable(){ $content = '<table style="border: 1px solid #000">'; $content .= '<tr><td>Author</td><td>'. $this->getAuthor() . '</td></tr>'; $content .= '<tr><td>Name</td><td>'. $this->getName() . '</td></tr>'; $content .= '<tr><td>Number of pages</td><td>'. $this->getNumberOfPages() . '</td></tr>'; $content .= '<tr><td>Year</td><td>'. $this->getYear() . '</td></tr>'; $content .= '<tr><td>Publishing office</td><td>'. $this->getPublishingOffice() . '</td></tr>'; $content .= '<tr><td>Edition number</td><td>'. $this->getEditionNumber() . '</td></tr>'; $content .= '</table>'; return $content; } public function displayUnformatted(){ $content = '<div style="border:1px solid #ddd">'; $content .= '<label>Author:</label><div>'. $this->getAuthor() . '</div>'; $content .= '<label>Name:</label><div>'. $this->getName() . '</div>'; $content .= '<label>Number of pages:</label><div>'. $this->getNumberOfPages() . '</div>'; $content .= '<label>Year:</label><div>'. $this->getYear() . '</div>'; $content .= '<label>Publishing office:</label><div>'. $this->getPublishingOffice() . '</div>'; $content .= '<label>Edition number:</label><div>'. $this->getEditionNumber() . '</div>'; $content .= '</div>'; return $content; } } $book1 = new book; $book1->author = 'Abramenko I.A'; $book1->name = 'Drupal: User guide'; $book1->numberOfPages = 192; $book1->year = 2013; $book1->publishingOffice = 'Moscow'; $book1->editionNumber = 1; $book2 = new book; $book2->author = 'Leshkina S.O.'; $book2->name = 'Drupal: Fields, Images, Views'; $book2->numberOfPages = 200; $book2->year = 2013; $book2->publishinOffice = 'Moscow'; $book2->editionNumber = 1; print $book1->displayTable(); print $book2->displayUnformatted(); ?>
Möglichkeiten von PHP 5.1.3 und älter:
Um Eigenschaften (Variablen) in einer Klasse zu definieren, verwendet man das Wort var.
<?php
class myClass{
}
?>
Schauen wir uns ein Beispiel mit Arrays und Funktionen an:
<?php $newArray =array(1,2,3,4,5); function _increment_all_elements($customArray){ foreach($customArray as $key){ $customArray[] = $key+1; } return $customArray; } $newArray = _increment_all_elements($newArray); print_r($newArray); ?>
Das Beispiel an sich hat wenig Sinn: Wir fügen zu dem bestehenden Array seine eigenen Werte plus 1 hinzu. Aber wichtig ist, wie wir es getan haben – mit Funktionen, die die Basis des funktionalen Programmierens in PHP sind. Objekte nehmen eine besondere Rolle ein, das Programmieren mit ihnen heißt objektorientiert.
Wir werden später das Beispiel mit Objekten wiederholen. Aber zuerst muss man verstehen, was ein Objekt ist.
Objekte, wie Funktionen, können Funktionen und Daten verbinden, aber näher an der Realität. Zum Beispiel kann ein Produktobjekt Eigenschaften wie Preis, Gewicht, Breite, Länge haben. Die Nähe zur realen Welt erleichtert das Verständnis des Codes.
Objekte werden (normalerweise) als Instanzen einer Klasse erzeugt. Zum Beispiel kann das Objekt "Ball" eine Instanz der Klasse "Produkt" sein. Eine Klasse ist eine Verallgemeinerung mit Beschreibung von Eigenschaften und Funktionen, ein Objekt ist die Umsetzung dieser Klasse.
Lassen Sie uns unsere erste Klasse und Objekt erstellen:
<?php class WorkWithArray{ } ?>
Mit dem Wort class erstellen wir eine Klasse, in den geschweiften Klammern schreiben wir die Eigenschaften und Funktionen der Klasse. Funktionen in Klassen heißen Methoden, Variablen heißen Eigenschaften.
Fügen wir dem Objekt die erste Eigenschaft hinzu, ein Array:
<?php class WorkWithArray{ var $myArray = array(); } ?>
Nun hat unsere Klasse ein Array als Eigenschaft, auch Mitglieder oder Instanzvariablen genannt. Eigenschaften werden mit var deklariert.
Es wäre gut, auch eine Funktion hinzuzufügen:
<?php class WorkWithArray{ var $myArray = array(); function increment_all_elements($newArray){ foreach($newArray as $key){ $newArray[] = $key+1; } return $newArray; } } ?>
Funktionen werden ganz normal zu Klassen hinzugefügt. Nun erstellen wir ein Objekt der Klasse:
<?php $myObject = new WorkWithArray; print_r($myObject); ?>
Wir geben das Objekt mit print_r aus, so wie bei Arrays. Nun greifen wir auf das Objekt zu, wir haben eine Eigenschaft myArray und eine Methode increment_all_elements():
<?php class WorkWithArray{ var $myArray = array(); function increment_all_elements($newArray){ foreach($newArray as $key){ $newArray[] = $key+1; } return $newArray; } } $myObject = new WorkWithArray; $myObject->myArray = array(2,4,6,7); print_r($myObject); ?>
Wir greifen auf Eigenschaften mit dem Operator -> zu, das liest sich als "die Eigenschaft myArray gehört dem Objekt myObject".
Nun können wir die Methode benutzen:
<?php class WorkWithArray{ var $myArray = array(); function increment_all_elements($newArray){ foreach($newArray as $key){ $newArray[] = $key+1; } return $newArray; } } $myObject = new WorkWithArray; $myObject->myArray = array(2,4,6,7); $myObject->myArray = $myObject->increment_all_elements($myObject->myArray); print_r($myObject); ?>
Methoden und Eigenschaften werden mit -> angesprochen, der Methodenaufruf heißt "call". Wir rufen increment_all_elements auf und übergeben die Eigenschaft myArray als Parameter, dann überschreiben wir die Eigenschaft mit dem Ergebnis, somit geben wir das veränderte Array aus.
Dieses einfache Beispiel zeigt, wie man Objekte erstellt und auf ihre Eigenschaften und Methoden zugreift. Wir werden noch ausführlicher die objektorientierte Programmierung betrachten.