Site d’Emmanuel Saint-James
Philologie de la programmation
Classer et Typer, c’est tout ce que tu sais faire

Un exemple de classe héritant d’une autre et déclarant le type de ses variables et fonctions :
un validateur XML fondé sur la programmation événementielle de l’analyseur SAX disponible en PHP :

class sax_validateur_min {
   protected array $dtd;
   protected array $erreurs = array();
   function __construct(array $dtd)
   {
       $this->dtd =$dtd;
   }

   function ouvrante (XmlParser $phraseur, string $nom, array $attr) : void
   {
       if (!isset($this->dtd[$nom])) {
           $this->errreurs[]="Element $nom inconnu";
       } else {
           $att = $this->attributs($phraseur, $nom, $attr);
       }
   }

   function fermante (XmlParser $phraseur, string $nom) : void
   {}

   function texte (XmlParser $phraseur, string $texte) : void
   {}

   function attributs(XmlParser $phraseur, string $nom, array $attr) : array
   {
       $ok = array();
       $atts = $this->dtd[$nom][1];
       foreach ($atts as $att => list($type, $mode)) {
           if (isset($attr[$att])) {
               $ok[] = $att;
               unset($attr[$att]);
           } elseif ($mode == 'REQUIRED') {
               $this->erreur[]="Attribut $att de $nom absent";
           }
       }
       if ($attr) {
           $ids = join(" ", array_keys($attr));
           $this->erreur[]= . "$ids attributs de $nom inconnus";
       }
       return $ok;
   }
}

class sax_validateur_contenu extends sax_validateur_min {
   protected array $pile = array();
   protected array $ids = array();
   function ouvrante (XmlParser $phraseur, string $nom, array $attr) : void
   {
       if (!isset($this->dtd[$nom])) {
           $this->erreur[]= "Element $nom inconnu";
           array_push($this->pile, 'ANY');
       } else {
           $ok = $this->pile
               ? preg_match("@[^\w:-]" . $nom . "[^\w:-]@", end($this->pile))
               : ($nom == key($this->dtd));
           if (!$ok) $this->erreur[]= "Element $nom incongru";
           array_push($this->pile, ' ' . $this->dtd[$nom][0] . ' ');
           $att = $this->attributs($phraseur, $nom, $attr);
       }
   }
   function fermante (XmlParser $phraseur, string $nom) : void
   {
       array_pop($this->pile);
   }
   function texte (XmlParser $phraseur, string $texte) : void
   {
       if (trim($texte) AND !preg_match('@#PCDATA@', end($this->pile)))
           $this->erreur[] = "texte incongru";
   }
   function attributs(XmlParser $phraseur, string $nom, array $attr) : array
   {
       $attr = parent::attributs($phraseur, $nom, $attr);
       foreach ($attr as $nom => $val) {
           if ($this->dtd[$nom][1][0] == 'ID') {
               if (isset($this->ids[$val])) {
                   $this->erreur[] = "ID $val en double";
               } else {
                   $this->ids[$val] = 1;
               }
           }
       }
       return $attr;
   }
}