NoFollow Free!
SHIFT Weblog

Dieses Blog ist ein Online-Magazin für erfahrene Website-Entwickler und Webdesigner, die PHP und Webdesign lieben.

Allgemein, PHP

PHP: OOP Crashkurs, Teil 1

oopcc

Viele Softwareentwickler können sich das Leben ohne OOP (Objektorientierte Programmierung) gar nicht mehr vorstellen. Bereits seit PHP 4 sind wir in der Lage, unseren Code objektorientiert zu erstellen – allerdings sind die Möglichkeiten hier sehr begrenzt. Seit dem Einzug von PHP 5 stehen uns mächtige Werkzeuge zur Verfügung, um nahezu komplett objektorientiert arbeiten zu können.

Doch was bedeutet überhaupt “Objektorientierte Programmierung”? Die Idee hinter dieser Programmiermethode ist, einzelne Bereiche (Variablen und Funktionen) einer Anwendung in einer Klasse zu hinterlegen. Innerhalb des Objektes können diese Funktionen verschiedene Daten untereinander austauschen. Um die Klasse zu benutzen, wird eine Instanz von ihr erzeugt. Bei gründlicher Planung sind Klassen wiederverwendbar und können auch erweitert werden.

Wir nehmen als Beispiel ein Fahrzeug. Ein Fahrzeug hat verschiedene Eigenschaften. Eines davon könnte sein: “Anzahl der Räder: 4″. Oder “Farbe: Rot”. Oder “Höchstgeschwindigkeit: 220″. Funktionen innerhalb eines Objektes können mit diesen Werten agieren und diese auch beeinflussen. Es könnte beispielsweise eine Funktion “tuning” geben, die die Höchstgeschwindigkeit auf einen höheren Wert festlegt. Wie das alles funktioniert, erfahrt ihr später. Wichtig ist erst einmal zu begreifen, was ein Objekt ist, was ein Klasse ist und was es beinhalten kann.

Inhalt:

Teil 1: Erstellen und Benutzen einer einfachen Klasse

Aufbau einer Klasse

Eine Klasse besteht aus Methoden und Eigenschaften. Methoden sind einfach nur Funktionen, die in einem Objekt stehen. Eigenschaften sind Variablen innerhalb einer Klasse und können auch “Attribut” oder “Membervariable” genannt werden. Da Beispiele immer besser sind als trockener Text, hier einmal eine sehr einfache Klasse:

class TolleKlasse {

	// Eigenschaft
	public $foo = 5;

	// Methode
	public function bar() {
		echo 'Hallo OOP!';
	}
}

Die Benutzung dieser Klasse kann erst dann erfolgen, wenn wir eine Instanz erzeugt haben. Eine Instanz ist ein Exemplar unserer Klasse und wird immer einer Variable zugewiesen. Diese Variable ist dann ein Objekt. Wir können die Klasse nun so Benutzen:

// Instanziierung
$test = new TolleKlasse();

// Aufrufen der Eigenschaft "$foo"
echo $test->foo; #Ausgabe: 5

// Aufrufen der Methode "bar()"
$test->bar(); # Ausgabe: Hallo OOP!

Um von der Instanz aus auf die Methoden und Eigenschaften zugreifen zu können, benutzt man den Pfeil-Operator (‘->’).

Auf der offiziellen PHP-Seite habe ich zum Thema “OOP” ein Beispiel mit “Licht” gefunden. Ich finde es ganz passend und werde hier auch “Licht” als Beispielklasse nehmen.

Erste Überlegungen

Okay, wenn wir also “Licht” als Klasse darstellen – was für Eigenschaften und Funktionen kann es haben? Ich habe es erstmal auf das wesentliche beschränkt und nehme die Farbe vom Licht und den Status (an oder aus?) des Lichts. Diese beiden Werte speichere ich in den Variablen (Eigenschaften) $state und $color innerhalb der Klasse. Jetzt sollte es noch Methoden geben, mit der wir die Farbe des Lichtes bestimmen sowie die Lampe an- und ausschalten können. In PHP sieht eine einfache Lösung so aus:

class Licht {

	public $color = 'weiss';
	public $state = 'off';

	public function setColor($clr) {
		if($this->state === 'on') {
			echo 'Die Farbe des Lichtes kann nur verändert werden, wenn es aus ist!';
		} else {
			$this->color = $clr;
			echo 'Die Farbe des Lichtes wurde geändert.';
		}
	}

	public function switchOn() {
		$this->state = 'on';
		echo 'Das Licht (Farbe ' . $this->color . ') wurde ANgeschaltet';
	}

	public function switchOff() {
		$this->state = 'off';
		echo 'Das Licht (Farbe ' . $this->color . ') wurde AUSgeschaltet';
	}

}

In unser Klasse namens “Licht” haben wir zwei Eigenschaften (Farbe und Status) sowie drei Methoden, die die Eigenschaften verändern können. Vor den Methoden und Eigenschaften steht jeweils das Wort “public”. Das ist ein Schlüsselwort, dass die Sichtbarkeit definiert – doch dazu kommen wir später.

Wir weisen den beiden Eigenschaften gleich einen Wert zu. Das ist dann praktisch, wenn bei der späteren Benutzung der Klasse nicht sicher ist, ob eine benötigte Eigenschaft noch gesetzt wird und wird daher vordefiniert.

Innerhalb des Objektes können wir mit dem Schlüsselwort $this auf andere Methoden und Eigenschaften der Klasse zugreifen. Bei der Methode “setColor()” wird vor dem Setzen der Eigenschaft geprüft, ob das Licht aus ist: Im “laufenden Betrieb” lässt sich die Farbe des Lichts nicht ändern. Die Methoden “switchOn” und “switchOff” schalten das Licht aus- und an und geben dann eine Meldung aus (Für die Besserwisser: Es ist natürlich immer besser, wenn Funktionen die Werte per return zurückzugeben anstatt sie direkt auszugeben – für unseren Crashkurs ist das aber egal.).

Handhabung

Die Klasse wird nun wie folgt benutzt:

$tischlampe = new Licht();
$tischlampe->setColor('helles gelb');
$tischlampe->switchOn();

$discolicht = new Licht();
$discolicht->setColor('neon-grün');
$discolicht->switchOn();
$discolicht->switchOff();

$scheinwerfer = new Licht();
$scheinwerfer->switchOn();
$scheinwerfer->setColor('xenon-weiß');
$scheinwerfer->switchOff();
$scheinwerfer->setColor('xenon-weiß');
$scheinwerfer->switchOn();

$tischlampe->switchOff();
echo 'Zustand von $tischlampe: ' . $tischlampe->state;

Würde man den oben genannten Code ausführen, dann bekommen wir diese Ausgabe:

Das Licht (Farbe helles gelb) wurde ANgeschaltet

Das Licht (Farbe neon-grün) wurde ANgeschaltet
Das Licht (Farbe neon-grün) wurde AUSgeschaltet

Das Licht (Farbe weiss) wurde ANgeschaltet
Die Farbe des Lichtes kann nur geändert werden, wenn es ausgeschaltet ist!
Das Licht (Farbe weiss) wurde AUSgeschaltet
Das Licht (Farbe xenon-weiß) wurde ANgeschaltet

Das Licht (Farbe helles gelb) wurde AUSgeschaltet
Zustand von $tischlampe: off

Der Konstruktor

Der Konstruktor ist eine spezielle Methode einer Klasse, die bei der Instanziierung dieser automatisch abgerufen wird. Jede Klasse kann nur einen Konstruktor haben. Der Methodenname eines Konstruktors lautet immer __construct. Ich verändere die Klasse “Licht” nun ein wenig und füge außerdem einen Konstruktur hinzu:

class Licht {

	public $color;
	public $state;

	public function __construct($color, $state = 'off') {
		$this->color = $color;
		$this->state = $state;
                echo 'Ein neues Licht wurde registriert.';
	}

	public function setColor($clr) {
		if($this->state != 'off') {
			echo 'Die Farbe des Lichtes kann nur verändert werden, wenn es aus ist.';
		} else {
			$this->color = $clr;
		}
	}

	public function switchOn() {
		$this->state = 'on';
	}

	public function switchOff() {
		$this->state = 'off';
	}

	public function status() {
		$status = ($this->state == 'on') ? 'ANgeschaltet' : 'AUSgeschaltet';
		return 'Das Licht (Farbe ' . $this->color . ') ist momentan ' . $status . '.';
	}

}

Wie ihr seht, habe ich auf fast alle echo-Ausgaben verzichtet und eine Methode hinzugefügt, die uns den Status des Lichtes zurückgibt. Der Konstruktor erwartet mindestens einen Parameter: Diese weisen wir direkt bei der Instanziierung zu:

$taschenlampe = new Licht('blau', 'on'); // Ausgabe: Ein neues Licht wurde registriert.
$nachtlicht = new Licht('rot'); // Ausgabe: Ein neues Licht wurde registriert.

$nachtlicht->switchOn(); // Keine Ausgabe
echo $nachtlicht->status(); // Ausgabe: Das Licht (Farbe rot) ist momentan ANgeschaltet.
echo $taschenlampe->status(); // Ausgabe: Das Licht (Farbe blau) ist momentan ANgeschaltet.

Ein Konstruktor ist immer praktisch, wenn der Benutzer direkt bei der Instanziierung einige Parameter angeben soll. Wie wir im Beispiel oben sehen, erspart uns der Konstruktor das Aufrufen der Methode setColor().

Statische Methoden

Statische Methoden sind Funktionen innerhalb einer Klasse, die man auch ausführen kann ohne dass eine Instanz der Klasse erzeugt wurde. Um statische Methoden auszuführen, müssen wir den Namen der Klasse nennen, danach zwei Doppelpunkte (‘::’) setzen und dann den Funktionsnamen angeben. Hier einmal ein simples und sinnloses Beispiel:

class Umrechner {

	public static function centimeter_to_meter ($cm) {
		return $cm / 100 . ' meter';
	}

	public static function decimeter_to_meter ($dm) {
		return $dm / 10 . ' meter';
	}

}

echo '150cm sind ' . Umrechner::centimeter_to_meter(150); // Ausgabe: 150cm sind 1,5 meter

Statische Methoden werden mit dem Schlüsselwort “static” markiert und erfordern dann keine Instanz der Klasse mehr, um die Funktion zu benutzen. Das bedeutet aber auch, dass wir innerhalb von statischen Methoden nicht mit dem Schlüsselwort $this auf andere Elemente der Klasse zugreifen können. Aus diesem Grund machen statische Funktionen nur selten Sinn.

Das war’s für den ersten Teil – die nächsten Teile werde ich auch bald fertigstellen.

 

Kommentare

Auf dieses Thema gibt es 12 Reaktionen

  1. Hi, ich bin’s mal wieder ;)

    Grundsätzlich ist ein OOP Tutorial nicht verkehrt, die Tatsache, dass statische Methoden selten Sinn machen finde zu kurz erläutert: denn sie machen Sinn, wenn der Kontext stimmt.

    Auf http://github.com/iuvare/evoext liegt ein gutes Beispiel: Einen Presenter. Die Art UND die Anzahl der erlaubten Instanzen werden im Controller definiert. Dessen Constructor ist private, man bekommt immer nur eine Insanz, das nennt sich Singleton. Also Controller::getInstance()

    Jetzt habe ich ein Object und kann mir mit der Methode $controller->getPresenter( $type ) einen Presenter holen. Da die Controller aber Sigleton ist, kann ich mir logischerweise nur jeweils einen Presenter holen. Hmm aber was mache ich wenn ich nen xml mit ldap brauche? Gleichzeitig was für SQL?

    Die Lösung ist eine statische Methode: Controller::factoryPresenter( $type, $extra )

    Warum also statisch? wenn ich weiß, dass ich mehrere Presenter brauche, muss ich kein Controller Object instanzieren, der eh singleton ist. Ist weit hergegriffen, ich weiß, aber man kann sich den Code zum Kommentar ja ansehen ;)

    Gruß Tim

  2. nikosch

    Ich muss mal kleinkariert kommentieren:
    Ich finde die Mischung von deutsch- und englischsprachigen Bezeichnern etwas daneben. Warum Du mal $clr und mal $color schreibst ist auch nicht klar.
    Auch würde ich von „Beleuchtung“ sprechen, nicht von Licht.

    In decimeter_to_meter ist auch ein c&p Fehler (falsche Variable).

    • Danke für den Hinweis, der c&p-Fehler wurde bereinigt.

      Ich habe deutsche und englische Begriffe aus zwei Gründen genommnen: Zum einen soll der Neuling die Sachbegriffe in beiden Sprachen aufnehmen. Zum anderen wollte ich innerhalb des Textes wenig Wortwiederholungen haben.

      Zum Thema $clr und $color: Ich habe mir angewöhnt, innerhalb von Methoden nur kurze Variablennamen zu verwenden, da diese später nicht mehr gebraucht werden. Eigenschaften schreibe ich immer ausführlich.

  3. Leider erst jetzt gelesen: Sehr schön und “griffig” geschrieben. Ein interessanter Anfang für eine Einführung, empfehlenswert.

    Ich warte gespannt auch die angekündigten weiteren Teile :-)

  4. Die gegenwärtige Version des Tutorials ist meines Erachtens sehr gelungen.

    Tims Hinweis, statische Methoden seien zu kurz abgehandelt, ist zwar sicherlich richtig, aber der Verweis auf das Factory-Pattern scheint mir in diesem Kontext übertrieben. Ich sehe die Gefahr eher darin, dass Anfänger statische Methoden dazu missbrauchen, prozeduralen Programmierstil als Objektorientierung zu tarnen. Die “feineren Punkte” statischer Methoden würden hier nur zu Verwirrung führen, denke ich.

    Wie wäre es übrigens mit den Bezeichnungen Instanzvariable/-methode (nicht statisch) und Klassenvariable/-methode (statisch)? Ich finde die recht logisch und trennscharf.

    Bei if($this->state != ‘off’) { könntest du den Vergleich noch typsicher machen. Das ist zwar eine Kleinigkeit, aber ich halte die typsicheren Vergleiche für eine Stärke deiner Beispiele.

    Gruß Marc

  5. Chris

    hey, an sich ein gutes tutorial, aber üble fehler ! im abschnitt KONSTRUKTUR zB in Zeile 29:

    $status = ($this->status == ‘on’) ? ‘ANgeschaltet’ , ‘AUSgeschaltet’;

    das wirft nen dicken syntaxfehler.
    diese komische schreibweise ist mir auch völlig unbekannt, vllt wäre es besser da ganz basic ranzugehen damit auch jeder versteht was hier passiert.

    lg

  6. Chris

    ich nochmal,
    weitere fehler: es muss $this->state anstatt $this->status heissen

  7. Ralf

    Hallo,

    > Der Konstruktor erwartet mindestens einen Parameter:

    Vielleicht noch als Anmerkung: Der Konstruktor erwartet _in diesem Beispiel_ mindestens einen Parameter. Generell kann er auch keinen Parameter haben, wie im Teil 2 zu sehen ist.

    Ich bin gerade drüber gestoplert und wollte mir schon merken: “Ein Konstruktor erwartet mindestens einen Parameter.” (also generell, immer)

    Gruß,
    Ralf

Hinterlasse eine Antwort

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

*

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">

 

Weitere Artikel der Kategorie PHP

PHP

Mein Verständnis von MVC

MVC – diese drei Buchstaben haben es in sich. MVC ist ein Design Pattern, eine strukturelle Lösung für Entwickler. Kaum ein anderes Design Pattern löst so viel Kontroverse aus und regt zu endlosen Diskussionen an – zumindest in der PHP-Welt. Das liegt daran, dass MVC recht oberflächlich beschrieben wird, und möchte man sämtliche MVC-Erklärungsversuche zusammenfassen,

Weiterlesen ›

PHP

Ausnahmezustand: PHP und Exceptions

Mit PHP 5 wurde dem Entwickler ein Werkzeug zur Verfügung gestellt, dass es in anderen objektorientierten Sprachen wie C++ und Python schon lange gibt: Exceptions. Mit diesen hat der Entwickler die Möglichkeit, auf ungewollte Ereignisse zu reagieren. Exceptions werden “geworfen”, das bedeutet, sie unterbrechen den normalen Programmfluss und behandeln eine eventuelle Ausnahme, die den weiteren

Weiterlesen ›

PHP, Quickies

Snippet: Geldbeträge mit PHP bereinigen

Folgendes Szenario: Ein Benutzer einer PHP-Applikation muss einen Geldbetrag eingeben. Für die Weiterberechnung und Speicherung dieses Betrages erwartet PHP ein Format wie 123 oder 567.89, nicht aber 246,80 oder 500,-. Bevor dem Benutzer der Applikation lange Erklärungen geben, wie eine solche Eingabe auszusehen hat, sollten wir uns selbst um die Bereinigung der Geldbetrageingabe kümmern. Wenn

Weiterlesen ›