PHP 5: Type Hinting und instanceof

Auch in der Version 5 ist PHP keine streng typisierte Sprache. Sie legen als Programmierer beim Schreiben eines Skripts also nicht fest “die Variable x ist ein string”.

Variablen haben zur Laufzeit zwar einen bestimmten Typ, aber der kann sich im Laufe des Skripts durchaus ändern. Beispielsweise haben als Parameter übergebene Werte generell den Typ String. Sobald Sie diese aber in einer Operation verwenden, die einen numerischen Wert voraussetzt, findet automatisch eine Typumwandlung statt.

Das ist bequem, weil man im Bezug auf Typen keine großen Festlegungen treffen muss und die automatische Typumwandlung in der Regel das erreicht, was man als Programmierer geplant hat. Die laxe Handhabung von PHP besitzt aber auch ihre Tücken. So ergibt etwa der Vergleich zwischen der Zahl 1 und dem String »1« keine Identität; beide Werte mit einer beliebigen Zahl addiert, sind dann aber wieder doch identisch, weil der String dabei automatisch in eine Zahl umgewandelt wird.

In Bezug auf Objekte als Parameter für Funktionen und Methoden gibt es nun eine kleine Hilfestellung. Das so genannte Type Hinting erlaubt es, dass man vor jedem Parameter einen Klassennamen schreiben kann, dessen Einhaltung durch den jeweiligen Parameter bei jedem Aufruf verifiziert wird:

<?php

// Beispiel OOP

// Type Hinting

class MutterKlasse{

   var $dummy;

   }

class TochterKlasse extends MutterKlasse {

   var $dummy2;

}  

class AndereKlasse {

   var $dummy3;

}  

function func_M(MutterKlasse $param) {

   // Rumpf leer, weil fuer das Beispiel irrelevant

   }

function func_T(TochterKlasse $param) {

   // Rumpf leer, weil fuer das Beispiel irrelevant

   }

$objMutter = new MutterKlasse();

$objTochter = new TochterKlasse();

$objAnders = new AndereKlasse();

// akzeptiert, weil identische Klasse

func_T($objTochter);

// akzeptiert, weil der Parameter eine

// Instanz der abgeleiteten Klasse ist

func_M($objTochter);

// Hier kommt der gezeigte Typfehler

func_T($objAnders);

// Typfehler, da die Basisklasse der

// geforderten Klasse nicht erlaubt ist

func_T($objMutter);

?>

Wie Sie im Beispiel sehen, lässt das Type Hinting die Verwendung eines Objekts zu, das von einer Ableitung der genannten Klasse stammt.

Umgekehrt geht das aber schief: Wird eine bestimmte Klasse als Parametertyp angefordert, genügt also ein Objekt nicht, das in der Klassenhierarchie höher steht, also ein Vorfahr des geforderten Typs ist. Das ist auch sinnvoll, denn ein Nachfahr einer Klasse beherrscht ja immer die Methoden der Basisklasse. Ein Vorfahr hingegen kann in der Regel nicht alle Methoden und Instanzvariablen seiner Nachkommen aufweisen.

Das Type Hinting könnte man durch die Verwendung des Operators

instanceof

auch anders realisieren. Der Operator instanceof prüft, ob eine Instanzvariable von einer bestimmten Klasse stammt.

Dazu formuliert man beispielsweise den folgenden Ausschnitt aus dem letzten Skript

function func_M(MutterKlasse $param) {

   // Rumpf leer, weil fuer das Beispiel irrelevant

   }

so um:

function func_M($param) {

   if (!($param instanceof MutterKlasse)) {

      die(“Parameter muss vom Typ MutterKlasse sein!”);

   }

Sie sehen, dass die Verwendung des Type Hinting um einiges kürzer und vor allem bequemer zu verwenden ist. Allerdings ist instanceof auch für andere Zwecke einsetzbar. So könnte man diesen Operator verwenden, um innerhalb einer Methode je nach der Klassenzugehörigkeit eines beim Aufruf verwendeten Parameters verschiedene Zweige zu durchlaufen.

Das folgende Beispiel implementiert eine Klasse für eine kleine Autofähre. Sie kann maximal 10 Personen und 1 Auto mitnehmen. Ein Lkw passt nicht hinein, weshalb ihre Lade-Methode aufnehmen mit einem Objekt der Klasse Lkw nicht umgehen kann.

<?php

// Beispiel OOP

// Operator instanceof

class Person {

   // kein Inhalt, weil fuer das Beispiel

   // nicht wichtig

   }

class Auto {

   // kein Inhalt, weil fuer das Beispiel

   // nicht wichtig

   }

class Lkw {

   // kein Inhalt, weil fuer das Beispiel

   // nicht wichtig

   }

  

  

  

class Autofaehre{

   var $nAnzAutos;

   var $nAnzPersonen;

   // Konstruktor setzt Instanzvars auf 0  

   function Autofaehre(){

      $this->nAnzAutos = 0;

      $this->nAnzPersonen=0;

      }

      

   // Autos und Personen aufnehmen

   function aufnehmen($obj){

      if ($obj instanceof Person){

         if ($this->nAnzPersonen < 10){

            $this->nAnzPersonen++;

            echo “eine Person geladen, habe nun “;

            echo “$this->nAnzPersonen Person(en) “;

            echo “an Bord<br>”;

         }

         else {

            echo “kein Platz mehr für eine “;

            echo “Person!<br>”;  

            }  

         }

      elseif ($obj instanceof Auto){

         if ($this->nAnzAutos < 1){

            $this->nAnzAutos++;

            echo “ein Auto geladen, habe nun “;

            echo “$this->nAnzAutos Auto an “;

            echo “Bord<br>”;

         }

         else {

            echo “kein Platz mehr für ein “;

            echo “Auto!<br>”;  

         }      

      }

      else {

         echo “Ich weiß nicht, wie ich etwas vom “;

         echo “Typ <i>” . get_class($obj) .”</i> “;

         echo “laden soll!<br>”;

      }

   }

}

// Objekte anlegen      

$objFaehre = new Autofaehre();

$objAuto1 = new Auto();

$objAuto2 = new Auto();

$objPersonA = new Person();

$objLkw1 = new Lkw();

// Faehre beladen

$objFaehre->aufnehmen($objAuto1);

$objFaehre->aufnehmen($objAuto2);

$objFaehre->aufnehmen($objPersonA);

$objFaehre->aufnehmen($objLkw1);

?>

Ähnliche Beiträge