Was ist objektorientierte Programmierung?
Die gängigen Erklärungen arbeiten mit Hunden, Katzen und Fahrzeugen. Dieser Text erklärt die vier tragenden Ideen an einer Aufgabe, wie sie in Fachanwendungen tatsächlich vorkommt — und nennt, wo die Idee an Grenzen stößt.
Das lernen Sie
Ein Objekt ist ein Ding mit Regeln
Ein Array kann alles enthalten. Ein Objekt enthält genau das, was seine Klasse vorsieht, und es achtet selbst darauf, dass es in einem gültigen Zustand bleibt. Das ist der ganze Unterschied — und er ist groß.
// Als Array: nichts hindert daran, Unsinn abzulegen
$urlaub = ['von' => '2027-08-01', 'bis' => '2027-07-01'];
// Ende vor Beginn — faellt erst irgendwo spaeter auf
// Als Objekt: der Fall kann gar nicht entstehen
final class Urlaubszeitraum
{
public function __construct(
public readonly DateTimeImmutable $von,
public readonly DateTimeImmutable $bis,
) {
if ($bis < $von) {
throw new InvalidArgumentException('Ende liegt vor dem Beginn.');
}
}
}Kapselung: nach außen nur, was gebraucht wird
Kapselung heißt, dass die Daten eines Objekts nicht von außen verändert werden können, sondern nur über Methoden, die die Regeln kennen. Praktisch bedeutet das: Wenn eine Regel sich ändert, muss man sie an einer Stelle ändern, nicht in allen Aufrufern suchen.
Der Gegentest ist einfach: Lässt sich ein Objekt von außen in einen Zustand bringen, den es laut Fachlichkeit nicht geben darf? Dann fehlt die Kapselung.
Schnittstellen: der wichtigste Teil
Eine Schnittstelle — im Sinne der Sprache, nicht im Sinne einer Datenübertragung — legt fest, was ein Objekt können muss, ohne zu sagen, wie. Das klingt abstrakt und ist der praktischste Teil der ganzen Idee.
interface Benachrichtigung
{
public function sende(string $empfaenger, string $text): bool;
}
final class EMailBenachrichtigung implements Benachrichtigung
{
public function sende(string $empfaenger, string $text): bool
{
// ... tatsaechlicher Versand
return true;
}
}
// Der Aufrufer kennt nur die Schnittstelle:
function informiere(Benachrichtigung $weg, string $an): void
{
$weg->sende($an, 'Ihr Auftrag wurde angenommen.');
}Genau dafür sind Schnittstellen da: Sie trennen die Entscheidung „was soll passieren" von der Entscheidung „womit". In einem Test lässt sich derselbe Platz mit einem einfachen Doppel besetzen, das nichts versendet, aber mitschreibt, was es bekommen hat.
Ein Beispiel aus der Praxis
Warum Vererbung seltener passt als gedacht
Vererbung verspricht, Gemeinsames einmal zu schreiben. In der Praxis entsteht daraus oft eine Kette, in der eine Änderung ganz oben an drei unerwarteten Stellen weiter unten wirkt. Die Frage, die hilft: Ist die Unterklasse wirklich eine Sonderform — oder benutzt sie nur etwas?
Ein Beispiel aus der Praxis: Eine „Eilbestellung" ist keine Sonderform einer „Bestellung" mit anderem Verhalten, sondern eine Bestellung mit einer anderen Lieferart. Als Vererbung gebaut, braucht die zweite Sonderform schon eine Mehrfachvererbung, die es nicht gibt. Als Eigenschaft gebaut, bleibt es eine Zeile.
Die gängige Faustregel lautet deshalb: erst zusammensetzen, erst dann vererben — und vererben vor allem dort, wo eine gemeinsame Schnittstelle sinnvoll ist.
Häufige Missverständnisse
Weiterführende Quellen
- PHP-Handbuch: Klassen und Objekte Kapselung, Vererbung, Interfaces
- PHP-Handbuch: Objekt-Interfaces die Sprachseite der Schnittstellen
Über den Autor
Fabian Lücker ist geschäftsführender Gesellschafter der PHP-Schmiede KG in Rheine und seit 2007 in der Softwareentwicklung tätig. Er verantwortet Entwicklung und Konzeption und schreibt hier über Entscheidungen, die in echten Projekten anfallen.