OO in php 5.3

Objektorientierte Programmierung mit PHP5 (Version 5.3)

In PHP4 und PHP5 wurden grundlegende objektorientierte Konzepte eingeführt. Hierbei wurde stehts auf Abwärtskompatibilität geachtet, sodass theoretisch PHP4-Anwendungen - objektorientiert oder nicht - auch mit PHP5 laufen müssten. In der Praxis kann es jedoch passieren, dass PHP4-Code nicht exakt dasselbe tut wie in PHP5. Darauf wollen wir jedoch hier nicht weiter eingehen, sondern den aktuellen Stand der Objektorientierung von PHP 5.3 betrachten.

Wer bereits OO-Erfahrung mit Java oder C# gesammelt hat, wird sich in PHP sehr schnell zurechtfinden, denn die Ähnlichkeit ist teils mehr als deutlich.

Konstruktor __construct()

Ein Konstruktor ist eine Funktion, die beim Instanziieren einer Klasse aufgerufen wird. In PHP 5.3 wird ein Konstruktor wie folgt realisiert:

class MyClass
{
    public function __construct()
    {
        //Add some code here
    }
}

Instanziieren der Klasse:

$myObject = new MyClass();

Statt einem Konstruktor ohne Parameter lässt sich auch ein Konstruktor mit Parametern verwenden. In diesen Parametern können dann beim Instanziieren beispielsweise gleich Werte für Attribute übergeben werden:

class MyClass
{
    protected $number;
    public function __construct($number)
    {
        $this->number = $number;
    }
}

Instanziieren der Klasse:

$myObject = new MyClass(123);

Da sich PHP Funktionen nicht überladen lassen, kann man die Funktion __construct() nur einmal definieren. Man hat nur die Möglichkeit, Datentypen im Code zu überprüfen und Parameter optional zu machen und dann zu überprüfen. Mittels einer Fallunterscheidung lässt sich dann eine ähnliche Funktionalität wie das Überladen von Funktionen realisieren.

Der Konstruktor __construct() muss immer public sein, da er zwangsläufig immer bei der Instanziierung, also von klassenäußerem Code, aufgerufen wird.

Schnittstellen/Interfaces

Schnittstellen enthalten lediglich Signaturen von Funktionen, aber keine Implementierungen. Sinn des Entwurfsmusters Schnittstelle ist:

  • Man kann festlegen, welche Funktionen eine Klasse, die eine Schnittstelle implementiert, mindestens haben muss
  • Man kann die Implementierungen mittels Klasse austauschen. Da festgelegt ist, welche Funktionen implementiert sein müssen, kann die konkrete Implementierung transparent benutzt werden: Der Aufrufer sieht erstmal nichts davon, wie die Implementierung konkret erfolgt ist.
  • Schließlich kann man Schnittstellen noch mehrfach vererben.

interface Foo
{
    public function getMessage();
}
class MyFoo implements Foo
{
    public function getMessage()
    {
        // ...
    }
}
$f = new MyFoo();
$f->getMessage();

Abstrakte Klassen

Abstrakte Klassen sind zunächst normale Klassen, jedoch können Sie Funktionen ohne Implementierung enthalten. Eine solche Funktion wird ähnlich wie bei einer Schnittstelle (Interface) mittels einer Signatur definiert:

abstract class Foo
{
    abstract public function hello1($a);
    public function hello2($a)
    {
        echo $a;
    }
}

Um die Klasse Foo verwenden zu können, müssen wir eine neue Klasse Fooo schreiben, die Foo erweitert und die abstrakte Funktion hello1() implementiert:

class Fooo extends Foo
{
   //Jetzt muss hello1() implementiert werden!
   public function hello1($a)
   {
      echo $a;
   }
   //hello2 wird geerbt!
}

Nun können wir beide Funktionen benutzen:

$fooo = new Fooo();
$fooo->hello1('hi1');
$fooo->hello2('hi2');

[public | protected | private] function

Mit der Objektorientierung hält auch die Sichtbarkeit von Funktionen Einzug in PHP5. Damit wurden folgende Anforderungen an eine objektorientierte Programmiersprache umgesetzt:

  • Es kann definiert und damit kontrolliert werden, welche Funktionen von außerhalb eines Objektes aufgerufen werden dürfen.
  • Es kann definiert werden, welche Funktionen auch in abgeleiteten Klassen vererbt werden.
  • Es kann definiert werden, welche Funktionen nur innerhalb eines Objektes verwendet werden dürfen.

Class Foo
{
    // foo1() kann innerhalb eines Objekte
    // dieser Klasse und von außerhalb aufgerufen werden.
    public function foo1()
    {
    }
    // foo2() kann nur innerhalb eines Objektes
    // dieser Klasse oder innerhalb eines Objektes, das
    // eine abgeleitete Klasse dieser Klasse instanziiert
    // aufgerufen werden. Aber nicht von außerhalb.
    protected function foo2()
    {
    }
    // foo3() kann nur innerhalb eines Objektes
    // dieser Klasse aufgerufen werden. Aber nicht von außerhalb.
    // private lässt keine Vererbung zu.
    private function foo3()
    { 
    }
    public function foo4()
    {
        //z.B. Aufruf einer protected function:
        $this->foo2(); //$this= das aktuelle instanziierte Objekt dieser Klasse
    }
    public function foo5()
    {
        //z.B. Aufruf einer private function:
        $this->foo3(); //$this ist das aktuelle instanziierte Objekt dieser Klasse
    }
}

//Ableitung einer Klasse (Erweiterung)
Class Fooo extends Foo
{
    //erbt foo1() und foo2() von Foo
}

$foo = new Foo();: Instanziieren eines Objektes der Klasse Foo.

$foo->foo1();: public function kann ausgeführt werden.

$foo->foo2();: Wirft einen Fehler, da protected Funktion.

$foo->foo3();: Wirft einen Fehler, da private Funktion.

$foo->foo4();: protected function foo2() innerhalb foo4() aufrufbar.

$foo->foo5();: private function foo3() innerhalb foo5() aufrufbar.

 

$fooo = new Fooo();: Instanziieren eines Objektes der Klasse Fooo.

$fooo->foo1();: Vererbte public function kann ausgeführt werden.

$fooo->foo2();: Wirft einen Fehler, da protected Funktion.

$fooo->foo3();: Wirft einen Fehler, da private Funktion.

$fooo->foo4();: protected function foo2() innerhalb foo4() aufrufbar. foo2() wurde vererbt.

$fooo->foo5();: Wirft einen Fehler, da private function foo3() innerhalb foo5() nicht aufrufbar aufrufbar. foo3() wird nicht vererbt.

Parameterübergabe ByValue / ByReference

Normalerweise werden Parameter "ByValue" übergeben, das heißt, man übergibt die Parameter einer Funktion als Wert und bekommt zunächst nichts zurück:

function foo($x)
{
    $x = 1;
}
$a = 0;
foo($a);
echo $a; //liefert 0, $a hat sich nicht geändert.

Stattdessen kann man aber auch nur eine Referenz auf einen Wert als Parameter übergeben. Wird nun innerhalb der Funktion der Wert der Referenz manipuliert, steht der Wert auch in der übergebenen Variable, denn diese verweist ja auf denselben Wert.

function foo(&$x)
{
    $x = 1;
}
$a = 0;
foo($a);
echo $a; //liefert 1, $a wurde durch foo() verändert!

Auf diese Weise lassen sich auch mehrere Parameter zurückliefern, z. B. mit

function foo(&$p1, &$p3, &$p3)
{
}

Alternativ müsste man am Ende der Funktion ein Array liefern, wenn man mehrere Werte zurückgeben möchte:

function foo($p1, $p3, $p3)
{
    // ...
    return array($p1, $p2, $p3);
}

& (Ampersand / Kaufmännisches und) vor einem Funktionsnamen

Wird einem Funktionsnamen ein & vorangestellt, so liefert die Funktion eine Referenz auf den Wert statt den Wert.

function &foo()
{
    return "x";
}

Quelle: https://secure.php.net/references.return