# 5.4.3 Statische Aufrufe von Klassen

Bisher waren Sie es gewohnt, Objekte zu erzeugen, bevor Methoden aus einer Klasse verwendet werden können. Hier wird nun beschrieben, wie eine Klasse ohne die Erstellung von Objekten "statisch" genutzt werden kann. Dabei unterscheiden wir zwischen statischen Eigenschaften und statischen Methoden.

Durch das Schlüsselwort static wird symbolisiert, dass es sich um eine statische Eigenschaft (siehe Zeile 3) oder eine statische Methode (siehe Zeile 6) handelt. Statisch bedeutet hierbei, dass etwas gleichbleibend ist. Wird diese Methode mehrmals innerhalb einer Klasse oder sogar innerhalb eines Programmes mit einer Vielzahl von Klassen benötigt, erleichtert die Nutzung von static den schnellen wiederholten Aufruf.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?php
    class Hours {
        protected static $hours = 24;  // Statische Eigenschaft

        // Statische Methode
        public static function getHoursPerDay(): int {
            return self::$hours;
        }
    }

In einer Klasse selbst werden statische Eigenschaften durch self:: aufgerufen (siehe Zeile 8), statt wie bisher durch `$this->`. Möchte man auf eine statische Eigenschaft außerhalb der aktuellen Klasse zugreifen, ersetzt man das self durch den Klassennamen, in dem sich die Ursprungsmethode befindet, in unserem Beispiel also `Hours::$hours`.

Dadurch, dass man dank statischer Methoden kein Objekt deklarieren muss, können sie global verwendet werden. Doch die Globalität statischer Methoden und Eigenschaften gegenüber der Verwendung lokal gültiger (new) Objekte hat große Nachteile:

- (a) die Übersichtlichkeit geht schneller verloren,
- (b) eine hohe Fehleranfälligkeit beim späteren Verändern der Methoden und
- (c) die dauerhafte Bindung der Klassen bei statischen Aufrufen nimmt die Möglichkeit die Funktionalität auszutauschen. Dieses ist vor allem beim Testen ein großer Nachteil.

Hier ein funktionierendes Beispiel. In Zeile 18 wird die Methode der Basisklasse mit `parent::` aufgerufen. Ein Aufruf mit `self::` führt zum identischen Ergebnis, ist aber beim Lesen des Sourcecodes nicht so eindeutig. Also bitte `parent::` verwenden.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    <?php
    // Definition der Basisklasse Hours mit einer statischen Eigenschaft und einer statischen Methode
    class Hours {
        protected static $hours = 24;  // Statische Eigenschaft

        // Statische Methode
        public static function getHoursPerDay(): int {
            return self::$hours;
        }
    }

    // Definition der Unterklasse Minutes, die von Hours erbt
    class Minutes extends Hours {
        protected static $minutesPerHour = 60;  // Zusätzliche statische Eigenschaft

        // Statische Methode der Unterklasse
        public static function getMinutesPerDay(): int {
            return parent::getHoursPerDay() * self::$minutesPerHour;
        }
    }

    /////////////// Hauptprogramm ///////////////////

    // Zugriff auf die statische Methode der Basisklasse
    echo "Stunden pro Tag: " . Hours::getHoursPerDay() . "<br>";  // Ausgabe: Stunden pro Tag: 24

    // Zugriff auf die statische Methode der Unterklasse
    echo "Minuten pro Tag: " . Minutes::getMinutesPerDay() . "<br>";  // Ausgabe: Minuten pro Tag: 1440
    ?>

Warnung

Ganz übel ist sogar, dass man Methoden nicht einmal mit dem Schlüsselwort `static` versehen muss (nur bei dem statischen Aufruf von Eigenschaften ohne `static` gibt es eine Fehlermeldung). Man kann also Methoden gleichzeitig in Objekten als auch in statischen Aufrufen verwenden. So etwas bitte nie, never ever machen.

Wenn eine statische Methode später mal verändert wird, so bedeutet es, dass dies Auswirkungen auf jeden einzelnen Aufruf haben wird. Und dies ist sehr fehleranfällig. Statische Methoden sollte man immer gleich (also statisch) unangerührt belassen, also nie ändern.

### Wann man den statischen Aufruf wirklich braucht

Wenn man auf Methoden oder Eigenschaften aus einer Basisklasse (siehe UML-Diagramme verstehen) zugreifen möchte, dann verwendet man das Schlüsselwort parent:: für den statischen Aufruf. Befindet man sich in einer Unterklasse, kann man somit Methoden und Eigenschaften der Basisklasse einfach einbinden, ohne den vollen Namen der Klasse ausschreiben zu müssen. Das folgende Beispiel stellt dies in vereinfachter Form dar.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?php
    class Minutes extends Hours {     // Wir befinden uns in der Unterklasse

        public function __construct() {
            // Aufruf des Konstruktors der Basisklasse
            parent::__construct(int $hours);
            ...
        }
    }

Hinweis

Mit Ausnahme des hier gezeigten Aufruf des Konstruktors einer Basisklasse sollten Sie als Programmier-Anfänger*in keine statischen Methoden verwenden, sondern Objekte bilden. Es sei denn, dass Sie die Vor- und Nachteile von statischen Aufrufen genau kennen und genau wissen, warum Sie von der Regel abweichen.