In der objektorientierten Programmierung entspricht die Klasse dem gesuchten Konstrukt für das Zusammenfassen von Daten und Operationen in einer Einheit. In der Fachsprache der Objektorientierung nennt man die Daten die Instanzvariablen und die Operationen die Methoden der Klasse.
Eine Klasse dient als Bauplan für die Erzeugung von Objekten während der Laufzeit eines objektorientierten Programmes. Dieses besteht aus einem dynamischen Geflecht solcher Objekte.
Die Belegung der Instanzvariablen eines Objektes mit bestimmten Werten definiert dessen aktuellen Zustand.
Jedem Objekt lässt sich eine Klasse zuordnen, nach deren Vorgaben es erzeugt wurde. Den Objekten einer Klasse ist ihre Funktion gemeinsam, da sie über dieselben Methoden verfügen. Sie unterscheiden sich nur in ihrem Zustand voneinander.
Eine Methode definiert eine Operation, die auf dem Objekt ausgeführt werden kann. Sie ist mit dem Begriff der Prozedur vergleichbar.
Ein wesentlicher Aspekt der objektorientierten Programmierung liegt in der Autonomie der Objekte für die Entscheidung, welche Methode für die Reaktion auf eine Nachricht von außen aufgerufen wird. Der Begriff "Methodenaufruf" (in Analogie zum Prozeduraufruf in der prozeduralen Programmierung) ist zu unpräzise. Es gilt zwischen dem Senden einer Nachricht an ein Objekt (durch das Aufrufen einer Methode) und der Ausführung einer Methode durch das Objekt zu unterscheiden: Welche Methode tatsächlich ausgeführt wird, entscheidet das Objekt.
Dieses Zusammenfassen von Daten und Operationen in einer Einheit wird Kapselung genannt und bildet die Grundlage der objektorientierten Programmierung.
Mit diesem Geheimnisprinzip wird die Trennung von Nutzungs- und Implementierungsschicht, von Realisierung und Nutzung verfolgt: Ein Entwickler, der eine Klasse eines anderen Entwicklers verwenden möchte, braucht die internen Abläufe der Klasse nicht zu kennen, er verwendet nur die vereinbarte Schnittstelle.
Zu diesem Zweck wird den Instanzvariablen und Methoden einer Klasse bei ihrer Deklaration eine von drei möglichen Zugreifbarkeiten zugewiesen:
Wird keines der drei Schlüsselwörter private,
protected und public bei der
Deklaration einer Instanzvariablen beziehungsweise einer Methode angegeben, so
wird implizit die allgemeine Zugreifbarkeit
(public) angenommen.
Nicht verwechseln sollte man das Geheimnisprinzip mit einem
Sicherheitskonzept im Sinne einer Zugriffskontrolle, die sicherstellt, dass
nur berechtigte Objekte auf bestimmte Instanzvariablen und Methoden zugreifen
dürfen. Dies ist hier nicht gemeint. Vielmehr sollen für die Verwendung der
Klasse unwesentliche Details vor dem Verwender der Klasse verborgen werden,
wie beispielsweise die Verwaltung von Ressourcen. Es geht nicht darum, dass
er diese Details nicht wissen darf, sondern er
braucht sie nicht zu wissen. Dies erlaubt es dem
Programmierer einer Klasse, Implementierungsdetails zu ändern, ohne dass der
Verwender der Klasse Änderungen an seinem Code vornehmen muss. Die
Deklaration einer Methode als public kommt somit einer
Festlegung gleich, während die Implementierung von als protected
oder private deklarierten Methoden in einer späteren Version
oder Unterklasse (siehe „Vererbung“)
geändert werden kann.
Die Syntax für die Deklaration von Klassen, Instanzvariablen und Methoden betrachten wir in diesem Kapitel am Beispiel einer Klasse für den Zugriff auf eine MySQL-Datenbank. Die Minimalfunktionalität, die wir von einer solchen Klasse erwarten, umfasst Methoden für den Auf- und Abbau einer Verbindung zum Datenbankserver sowie Methoden für die Ausführung von Anfragen und die Verarbeitung von Ergebniszeilen, die von einer Anfrage geliefert werden.
Um die Struktur von Klassen, die Interaktionen zwischen Objekten oder die Abläufe innerhalb einer Methode zu illustrieren, verwenden wir Diagramme in der Notation der Unified Modeling Language (UML).
Eine Klasse wird in UML beispielsweise als Rechteck dargestellt, das durch
horizontale Linien in drei Bereiche aufgeteilt ist. Der obere Bereich
beinhaltet neben dem Klassennamen (fett) optionale Informationen,
beispielsweise über die Paketzugehörigkeit der Klasse. Die beiden anderen
Bereiche sind den Instanzvariablen und Methoden der Klasse vorbehalten. Die
Zugreifbarkeit von Instanzvariablen und Methoden wird durch Voranstellen von
+ (public), #
(protected) und -
(private) ausgedrückt.
Abbildung 1.1
zeigt ein UML-Klassendiagramm für unser Beispiel.
Die Implementierung dieser Klasse in PHP zeigt
Beispiel 1.2.
Das Beispiel verwendet die Pseudovariable
$this, die wir im Abschnitt über
Referenzen genauer betrachten werden. Die Verwendung der Klasse wird in
Beispiel 1.3
demonstriert.
Beispiel 1.2: Eine Klasse für den Zugriff auf eine MySQL-Datenbank
<?php
class DB_MySQL {
private $connection = NULL;
private $result = NULL;
public function connect($host, $database, $user, $pass) {
$this->connection = mysql_connect(
$host,
$user,
$pass,
TRUE
);
mysql_select_db($database, $this->connection);
}
public function disconnect() {
if (is_resource($this->connection)) {
mysql_close($this->connection);
}
}
public function query($query) {
if (is_resource($this->connection)) {
if (is_resource($this->result)) {
mysql_free_result($this->result);
}
$this->result = mysql_query(
$query,
$this->connection
);
}
}
public function fetchRow() {
if (is_resource($this->result)) {
$row = mysql_fetch_assoc($this->result);
if (is_array($row)) {
return $row;
} else {
return FALSE;
}
}
}
}
?>Beispiel 1.3: Verwendung der MySQL-Klasse
<?php
require_once 'DB_MySQL.php';
$mysql = new DB_MySQL;
$mysql->connect('localhost', 'test', 'root', '');
$mysql->query('SELECT spalte FROM tabelle');
while ($row = $mysql->fetchRow()) {
// ...
}
$mysql->disconnect();
?>Bei der Deklaration von Methoden erlaubt PHP die Angabe eines Klassen- oder Schnittstellennamens für als Parameter übergebene Objekte. Im Gegensatz zu statisch getypten Programmiersprachen erfolgt die Typprüfung jedoch nicht zum Zeitpunkt der Kompilierung, sondern erst zur Laufzeit. Diese so genannten Type Hints ersparen dem Programmierer Schreibarbeit, wie an Beispiel 1.4 und Beispiel 1.5 zu erkennen ist.
Beispiel 1.4: Typprüfung mit Type Hints
<?php
class Vector {
public function add(Vector $vector) {
// ...
}
}
?>Beispiel 1.5: Typprüfung mit dem instanceof-Operator
<?php
class Vector {
public function add($vector) {
if (!($vector instanceof Vector)) {
die('Parameter muss vom Typ Vector sein.');
}
// ...
}
}
?>
Beispiel 1.4
und Beispiel 1.5
sind semantisch äquivalent und unterscheiden sich nur in der Art der
Typprüfung durch die Type Hints beziehungsweise den
instanceof-Operator.