Statische Methoden sind zwar ein Teil einer Klasse und werden daher als Teil der objektorientierten Programmierung verstanden. Falsch eingesetzt sind sie aber nichts anderes als eigenständige Funktionen und daher prozeduraler Programmierstil.
Dieser Beitrag beschäftigt sich mit der Differenzierung dieser Problematik und ihr erfahrt, was tatsächliche Einsatzgebiete einer statischen Methode sind.
Was sind statische Methoden?
Sie werden in einer Klasse definiert und mit dem Schlüsselwort static
ausgezeichnet.
1 2 3 4 5 6 7 |
class BeispielKlasse { public static function sayHello() { echo 'Hello World.'; } } |
Sie können genau wie „normale“ Methoden alle drei Sichtbarkeiten (public
, protected
, private
) verwenden. Aufgerufen werden statische Methoden ohne eine Instanz der Klasse zu erzeugen und daher nicht mit einen ->
sondern mit ::
1 |
BeispielKlasse::sayHello(); |
Fun Fact: Der Name für den doppelten Doppelpunkt ist T_PAAMAYIM_NEKUDOTAYIM. Falls ihr dieses Token also im Errorlog seht, wisst ihr jetzt was es meint.
Ist das jetzt objektorientiert?
Nein! Das ist prozedurale Programmierung.
1 2 3 4 5 |
function sayHello() { echo 'Hello World.'; } sayHello(); |
Damit erreichen wir genau das selbe. Und wenn es um die Strukturierung ähnlicher Funktionen geht, dann ist ein Namensraum die viel bessere Wahl.
1 2 3 4 5 |
namespace BlaBla { function sayHello() { echo 'Hello World.'; } } |
Wann verwende ich statische Methoden?
Statische Methoden sind zum Beispiel dann sinnvoll, wenn bei der Erstellung von Objekten „geholfen“ werden soll. Bei vielen MVC, die dem Active Record Pattern folgen, werden die Models mit einer statischen find()
Methode aus der Datenbank geladen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class User extends BaseModel { public $name; /** * @param $name * * @return self|false */ public static function findOneByName($name) { /** @var \PDO $pdo */ $pdo = parent::getDb(); $stmt = $pdo->prepare('SELECT * FROM users WHERE name = :name'); $stmt->bindParam(':name', $name); return $stmt->fetchObject(__CLASS__); } } |
1 2 3 4 5 |
$user = User::findOneByName($_GET['name']); if (!$user instanceof User) { throw new \UnexpectedValueException('user not found'); } |
Der Anwender müsste andernfalls den Datensatz selbst aus der Datenbank laden und dann über new User()
ein Objekt erzeugen. Das würde sehr schnell zu dupliziertem Code führen und wäre nicht sehr sinnvoll.
Ein weiterer Anwendungsfall wäre ein Singleton.
Zugriff innerhalb der Klasse
Innerhalb der selben Klasse werden statische Methoden auf zwei Arten angesprochen: Entweder mit dem Schlüsselwort static
oder mit self
.
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
class Animal { public static function sayWorld() { echo 'Hello world!'; } } class Cat extends Animal { public static function sayHello() { echo 'Hello cat!'; } public function saySomething() { // Greift auf die selbe Klasse zu, auch wenn saySomething von einem Kind aus aufgerufen wird. // Äquivalent zu Cat::sayHello() self::sayHello(); // Erlaubt Kindklassen die Methode zu überschreiben. static::sayHello(); // Methoden der Eltern können auf beide Weisen angesprochen werden. self::sayWorld(); static::sayWorld(); } } class Kitty extends Cat { public static function sayHello() { echo 'Hello kitty!'; } } $kitty = new Kitty(); $kitty->saySomething(); /* Ausgabe Hello cat! Hello kitty! Hello world! Hello world! */ |
Außer ihr wollt explizit verhindern, dass eine Kindklasse die Methode überscheibt, solltet ihr also static
verwenden.
Probleme beim Unit-Testing
Da bei der Verwendung statischer Methoden, der Klassenname explizit hingeschrieben werden muss, kann ein Test diesen nicht durch ein Mock-Objekt ersetzen. Oft werden an dieser Stelle die Tests dann sehr aufwendig.
Fazit
Statische Methoden sind zwar ein Teil der objektorientierten Programmierung und haben durchaus ihre Berechtigung, dennoch solltet ihr euch jedes Mal gut überlegen, ob ihr das Problem nicht anders besser lösen könnt.
Was dich noch interessieren könnte:
Schöne, kompakte Darstellung von static.
Aber auch wenn mit ’static‘ definierte Methoden nicht die schönste Art der OOP sind: Ich sehe aber nicht, dass sie ähnlich beschränkt wären wie klassische Funktionen. Schließlich hätte eine Klasse/ Objekt bei einer entsprechend einfachen Umsetzung auch nicht mehr Funktionalität als eine Funktion.
Ein wichtiger Unterschied ist, dass auch bei einer statischen Methode ein Zugriff auf die Attribute der Klasse möglich ist – und deren Lebensdauer geht über den Aufruf der Methode hinaus. Die Datenhaltung arbeitet also gänzlich anders als bei Funktionen. Lediglich das instantiierte Objekt fehlt bei statischen Methoden. Und Instantiierung ist für sich genommen nicht einmal ein zwingendes Merkmal der OOP.
Viele Grüße
Stephan