Właśnie zaimplementowałem proste sprawdzanie typów w PHP5. Oczywiście, nie jest to C++, gdzie kontrola ta jest bardziej ścisła, ale myślę że w wielu wypadkach starczy. Jest to o tyle wygodne, że łatwiej nieco będzie wykrywać nieścisłości (zresztą, po to jest sprawdzanie typów).

Przykład kodu:

class Test
{
  protected $properties = array(
    'var1' => array('tralala', 'string'),
    'var2' => array(3, 'integer'),
    'var3' => array(array('tralala', 'bulcykcyk), 'array')
  );
  public function __set($key, $value)
  {
    if (!array_key_exists($key, $this->properties)) {
      throw new Exception(sprintf('"%s" property doesn\'t exists.', $key));
    }
    if (gettype($value) != $this->properties[$key][1]) {
      throw new Exception(sprintf('"%s" property must be an "%s" type, is "%s".',
          $key,
          $this->properties[$key][1],
          gettype($value)
      ));
    }
    $this->properties[$key][0] = $value;
  }
}

Najtrudniejszym elementem jest tutaj każdorazowe ustawianie właściwej konstrukcji zmiennej $properties, ponieważ ta tablica ma konkretny format:

$properties = array(
  'nazwa_zmiennej' => array('wartość', 'typ')
)

Jako ‘wartość‘ wstawiamy tam wartość właściwości (obojętnie, czy obiekt, int, string, tablicę czy coś innego), a jako ‘typ‘ - wartość zwracana przez funkcję getttype() wywołaną na przechowywanym obiekcie. Dla napisów będzie to wartość ‘string‘, dla liczb całkowitych: ‘integer‘, a dla obiektów: ‘object‘.

Ta kontrola typów jest o tyle uproszczona, że nie sprawdza, czy przechowywany obiekt jest instancją danej klasy (tej która ma być przechowywana), oraz czy tablica przechowuje żądany typ obiektów. O ile pierwsze czasem warto, i łatwo zrobić za pomocą is_a() czy też get_class(), o tyle drugie może być trudniejsze i wymagać funkcji dodatkowych (jeśli sprawdzanie ma być niezależne od ilości zagłębień tablicy).

Przykład użycia:

$a = new Test;
try {
  $a->var1 = 'asd';               //ok
  $a->var2 = 1;                   //ok
  $a->var3 = array(1, 2, 3);  //ok

  //$a->var1 = 1;              //exception!
  //$a->var2 = 'a';             //exception!
  //$a->var3 = 1;              //exception!
} catch (Exception $e) {
  echo $e->getMessage();
}

W moim wypadku najlepszym rozwiązaniem było utworzenie klasy ‘Test‘ jako abstrakcyjnej (’abstract‘) i tworzenie kolejnych klas jako dziedziczących z niej. Każde z dzieci musi oczywiście mieć swoją wersję tablicy ‘$properties‘.


A Ty? Co o tym myślisz?

Możesz używać w komentarzach następujących znaczników:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Sblam! Antyspam