PHP 5 objektorientiert: Eine Einführung

Bis zur Version 4 war  nur halbherzig objektorientiert. Zwar konnten Programmierer Klassen schaffen und ihnen Methoden geben. Doch bei OOP-Standards wie dem Überladen von Klassen oder Zugriffsmodifizierern wie »private« und »protected«, die Instanzvariablen vor der Außenwelt abschirmen, musste das alte PHP passen. Einheitlich benennbare Konstruktoren und Destruktoren fehlten ebenso wie die Möglichkeit, Default-Aktionen in Klassen zu definieren.

Mit PHP 5 steigt die Skript-Sprache in die Liga der objektorientierten Sprachen auf. Wer mit den Konzepten von Java, C++ oder C# vertraut ist, wird sich mit PHP schnell zurechtfinden.

Einsteiger und Freunde der strukturellen Programmierung müssen dennoch nicht verzagen. PHP bleibt selbstverständlich rückwärtskompatibel. Sie können also genauso schnell und effektiv Skripten schreiben wie zuvor. Und ein paar neue Funktionen liefert PHP 5 gleich mit dazu.

Private und Protected-Variablen und -Methoden

Objektorientierte Puristen haben über PHP 4 immer die Nase gerümpft – zu Recht: Denn in der Vierer-Version war es nicht möglich, Variablen und Methoden innerhalb einer Klasse vor einem Zugriff von außen zu schützen.

Gerade Programmierer, die in gemeinsamen Projekten arbeiten oder ihren Code weitergeben, brauchen aber ein solches Feature. Denn wenn jede und Methode von außen zugänglich ist, schafft das zusätzliche Fehlerquellen: Jeder andere Programmierer kann jederzeit eine beliebige Variable im Objekt ändern und damit unerwünschte und unerwartete Resultate erzeugen.

Aber in PHP 5 ist das jetzt anders. Sie als Programmierer einer Klasse bestimmen, ob eine Variable von außen zugänglich ist oder nicht. Folgende Möglichkeiten gibt es:

  • Die Variable ist von außen zugänglich, darf gelesen oder geändert werden. Eine solche Variable deklarieren Sie als public.
  • Die Variable ist nur innerhalb der eigenen Klasse und in den Klassen zugänglich, die abgeleitet werden. Sprich: Eine Klasse, die eine andere beerbt, darf diese Variable lesen oder auch ändern. Das hierfür zuständige Schlüsselwort ist protected.
  • Kompletten Schutz bietet das Schlüsselwort private. Eine so deklarierte Variable darf weder von außen gelesen werden noch ist sie einer vererbten Klasse zugänglich.

Am folgenden Beispiel sehen Sie die Wirkung der drei unterschiedlichen Zugriffsmodifizierer auf die Sichtbarkeit der Instanzvariablen:

<?php

/**

* Beispiel fuer public, private und protected

*

*/

class TestClass

{

public $strPub = "Ich bin public";

protected $strProt = "Ich bin protected";

private $strPriv = "Ich bin private";

 

function showVars()

{

echo "Das sieht die Klasse TestClass:n";

echo "$strPub: $this->strPubn";

echo "$strProt: $this->strProtn";

echo "$strPriv: $this->strPrivn";

echo "n";

}

}

 

class ExtClass extends TestClass

{

function showVars()

{

parent::showVars();

echo "Das sieht die Klasse ExtClass:n";

echo "$strPub: $this->strPubn";

echo "$strProt: $this->strProtn";

// Die folgende Zeile zeigt nichts an

echo "$strPriv: $this->strPrivn";

echo "n";

}

}

 

$objTest = new TestClass();

$objExt = new ExtClass();

 

// Die Variablen innerhalb der Klasse ExtClass anzeigen

$objExt->showVars();

// Variablen ansehen

echo "Das sieht das Hauptprogramm:n";

echo "$objTest->strPub: $objTest->strPubn";

//echo "$objTest->strProt: $objTest->strProtn";

// echo "$objTest->strPriv: $objTest->strPrivn";

echo "n";

// Aenderungsversuche

// Eine public-Variable aendern

$objTest->strPub =

"Ich bin public, vom Hauptprogramm geändert!";

// Eine protected-Variable aendern --> FEHLER

// $objTest->strProt =

// "Ich bin protected. Das Hauptprogramm kann mich nicht

// ändern";

// Eine private Variable aendern --> FEHLER

// $objTest->strPriv =

// "Ich bin private. Das Hauptprogramm kann mich

// nicht ändern";

 

$objTest->showVars();

?>

In der TestClass deklarieren Sie drei Variablen (eine als public, eine als protected, eine als private) und belegen sie mit je einem String. Dazu liefert unsere Testklasse noch eine Methode showVars(), die einfach nur den Inhalt der Variablen anzeigen soll. Danach bauen Sie noch eine zweite Klasse auf: ExtClass erweitert unsere TestClass. Diese Klasse hat nicht mehr zu bieten als eine weitere showVars()-Methode. Die ExtClass ruft erst einmal dieselbe Methode bei der übergeordneten Klasse auf und gibt danach selbst den Inhalt ihrer Variablen aus.

Und genau an dieser Stelle stoßen wir auf den ersten Fehler, den dieses Skript erzeugt: Die dritte Zeile

echo "$strPriv: $this->strPrivn";

gibt nichts aus. Warum? Weil ExtClass als Nachkomme keinen Zugriff auf die als private deklarierte Variable $strPriv aus der Elternklasse hat. Je nach PHP-Installation erscheint übrigens eine Warnung wie:

Notice: Undefined property: extclass::$strPriv

Das Hauptprogramm instanziiert je einmal beide Klassen und ruft dann die Anzeige der Variablen auf.

Danach zeigt es den Inhalt der Variablen $strPub an. Unter der entsprechenden Zeile finden Sie noch zwei weitere, auskommentierte Zeilen. Kommentieren Sie eine von beiden ein, und starten Sie das Programm erneut – der Fehler ist fatal:

Fatal error: Cannot access protected property testclass::$strProt

In den letzten Zeilen versucht das Hauptprogramm, eine Variable zu ändern. Mit der als public definierten Variablen $strPub funktioniert das auch. Wenn Sie aber eine der folgenden Zeilen auskommentieren, gibt es wieder einen fatalen Fehler.

Genauso wie Variablen lassen sich Methoden schützen. Zum Beispiel:

<?php
/**
* Beispiel fuer private Methoden
*
*/
class TestClass
{
private function testMethod()
{
echo "Ich bin eine private Methode";
}
 
public function showText()
{
$this->testMethod();
}
}
$objTest = new TestClass();
 
// Funktioniert
$objTest->showText();
 
// FEHLER!
$objTest->testMethod();
?>

Die Klasse TestClass hat zwei Methoden. Die eine, als private deklarierte testMethod(), gibt einen kurzen Text aus. Die andere, showText(), ruft wiederum testMethod() auf.




Im Hauptprogramm wird zunächst showText() aufgerufen. Als Resultat auf dem Bildschirm sehen Sie den Text Ich bin eine private Methode. Danach probiert das Hauptprogramm, direkt testMethod() aufzurufen – und scheitert mit:

Fatal error: Call to private method testclass::testMethod()

So einfach ist es, Methoden zu schützen. Die Abstufungen gelten wie bei den Variablen.

Der Vorteil von private und protected: Der gesamte Programmcode wird robuster und leichter zu handhaben, wenn Variablen in Objekten vor unabsichtlichen Änderungen geschützt werden. Der kleine Nachteil: Der Aufwand erhöht sich ein wenig: Als Programmierer sollten Sie sich immer genau überlegen, welche Variablen und Methoden einer Klasse Sie exponieren.

Und was passiert mit den alten Variablen und Methoden in Ihren Klassen aus PHP 4? Sie werden weiterhin public zugänglich sein. Sofern Sie also kein anderes Schlüsselwort eingeben, bleibt alles beim Alten. Aber es lohnt sich, viel benutzte Klassen zu durchforsten und mit private und protected abzusichern.

Abstrakte Klassen

Abstrakte Klassen erlauben es, »Modelle« für Klassen herzustellen. Anhand dieser Modelle kann ein Programmierer dann seine eigenen Klassen bauen. Der Vorteil des Ganzen: Ein Programmierer kann mit solchen abstrakten Klassen unveränderliche Klassen bauen, auf denen viele weitere Klassen basieren dürfen. Da sie nicht verändert werden können, haben andere Programmierer die Gewissheit, dass der Code robust und flexibel wiederverwendbar ist.

Interfaces

Interfaces haben in PHP 5 eher eine Sicherungsfunktion. In einem Interface, zu Deutsch: einer Schnittstelle, legen Sie ein Set von Methoden fest. Wird dieses Interface in eine Klasse implementiert, so müssen für die Klasse Funktionen mit den im Interface festgelegten Namen programmiert werden. Fehlt eine Methode, meldet der Compiler einen Fehler.

Wozu dient das Ganze? Es erleichtert die Kontrolle über den Code und die Programmierung, sobald mehr als ein Programmierer an einem Projekt arbeitet. Über ein Interface legt man bestimmte Richtlinien fest, die jede Klasse einhalten muss – so läuft man weniger Gefahr, etwas zu vergessen, und der Code wird robuster.

Fehlerbehandlung mit try…catch

Mit try und catch bietet PHP endlich ein einheitliches Verfahren, um Fehler abzufangen und zu verarbeiten. Das Prinzip: Ein Codeblock wird von try{} umschlossen. Tritt innerhalb dieses Blocks ein Fehler auf, so fängt ihn catch{} ab.

Für das Erzeugen der Fehlermeldung ist throw verantwortlich. Sobald etwas schief geht, erzeugt diese Anweisung ein neues Objekt der Klasse Exception und übergibt ihr den Text einer Fehlermeldung. Selbstverständlich können Sie auch eigene Klassen zur erzeugen, um beispielsweise nach einem Fehler notwendige Aufräumarbeiten zu veranlassen oder genauere Meldungen auszugeben.

Das folgende Beispiel zeigt das Prinzip von try und catch:

<?php

/*

* Eine Beispielklasse fuer die Fehlerbehandlung

*/

class Calculation

{

// Diese Funktion teilt $x durch $y

function divide($x,$y)

{

// Pruefen, ob $y gleich 0, falls ja -> Fehlermeldung erzeugen

if($y == 0)

throw new Exception("Divisionsfehler ($y = $y)");

// Ergebnis zurueckgeben

return $x/$y;

}

}

// Hauptprogramm

$objCalc = new Calculation();

try

{

// Absichtlich einen Fehler erzeugen

$intResult = $objCalc->divide(99,0);

// Diese Meldung erscheint nur, wenn kein Fehler auftritt

echo 'Das Ergebnis: '.$intResult.'
';

}

// Die Fehlermeldung auffangen

catch (Exception $e)

{

// Methode zum Ausgeben der Meldung

echo $e->getMessage();

}

?>

Der große Vorteil: Beim Programmieren von Klassen und Funktionen müssen Sie sich nur noch darum kümmern, ob und mit welcher Begründung abgebrochen und eine Fehlermeldung erzeugt wird. Wie das Programm schließlich mit dem Fehler umgeht, regeln Sie später im Hauptprogramm.

Erzeugen von Properties

Mit den neuen Schlüsselwörtern protected und private schützen Sie Instanzvariablen vor dem direkten Zugriff durch Skripten. In gewisser Weise setzen die neuen Funktionen __get und __set noch eins drauf. Denn wenn man sie in einer Klasse implementiert, werden sie immer dann aufgerufen, wenn der Zugriff auf eine undefinierte Instanzvariable erfolgt.

Anhand des per Parameter übergebenen Namens dieser unbekannten Instanzvariablen lässt sich dann entscheiden, was zu tun ist. So könnte beispielsweise eine Klasse, die Wetterdaten eines Ortes enthält, eine Instanzvariable für die Temperatur in Grad Fahrenheit anbieten, obwohl intern die Temperatur nur in Grad Celsius gespeichert wird:

<?php

// Beispiel

// Die Verwendung von Property-Methoden

class Wetter {

// Instanzvariablen

var $nTempC;

var $nLuftdruckHPa;

var $nNiederschlag;

 

// Property-Methoden

function __get($strVarname) {

if ($strVarname=='nTempF'){

// Umrechnung Celsius -> Fahrenheit

return (($this->nTempC * 9 / 5) + 32 );

}

else {

return ("Variable '$strVarname' unbekannt!");

}

}

 

function __set($strVarname,$xValue) {

if ($strVarname=='nTempF'){

// Umrechnung Fahrenheit -> Celsius

$this->nTempC = ($xValue- 32) * 5 / 9;

$this->nTempC = round($this->nTempC*10) / 10;

}

else {

echo("Variable '$strVarname' unbekannt!");

}

}

}

$objWetter = new Wetter();

$objWetter->nTempC=25;

echo "25 °C entsprechen $objWetter->nTempF °F ";

$objWetter->nTempF = 90;

echo "90 °F entsprechen $objWetter->nTempC °C ";

// Ausgabe:

// 25 °C entsprechen 77 °F

// 90 °F entsprechen 32.2 °C

?>

Ähnliche Beiträge

1 Gedanke zu „PHP 5 objektorientiert: Eine Einführung“

  1. Anmerkung zu Interfaces:

    Interfaces lassen sich gut für Type Hinting einsetzen. (siehe PHP 5: Type Hinting und instanceof)
    Wenn Objekte von verschiedenen Klassen an eine Methode/ Funktion als ein Parameter übergeben werden können sollen, jedoch diese verschiedenen Klassen nicht einer Vererbungslinie folgen, können dafür Interfaces als Ersatz für Mehrfachvererbung genutzt werden (ähnlich Java).

    Bsp :

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *