Existe-t-il un travail décent autour du manque de PHP de génériques qui permettent l'inspection statique du code pour détecter la cohérence des types?
J'ai une classe abstraite, que je veux sous-classer et imposer également que l'une des méthodes passe de la prise d'un paramètre d'un type à la prise d'un paramètre qui est une sous-classe de ce paramètre.
abstract class AbstractProcessor {
abstract function processItem(Item $item);
}
class WoodProcessor extends AbstractProcessor {
function processItem(WoodItem $item){}
}
Ceci n'est pas autorisé en PHP car il modifie la signature des méthodes, ce qui n'est pas autorisé. Avec les génériques de style Java, vous pourriez faire quelque chose comme:
abstract class AbstractProcessor<T> {
abstract function processItem(T $item);
}
class WoodProcessor extends AbstractProcessor<WoodItem> {
function processItem(WoodItem $item);
}
Mais évidemment, PHP ne les prend pas en charge.
Google pour ce problème, les gens suggèrent d'utiliser instanceof
pour vérifier les erreurs au moment de l'exécution, par exemple
class WoodProcessor extends AbstractProcessor {
function processItem(Item $item){
if (!($item instanceof WoodItem)) {
throw new \InvalidArgumentException(
"item of class ".get_class($item)." is not a WoodItem");
}
}
}
Mais cela ne fonctionne qu'au moment de l'exécution, cela ne vous permet pas d'inspecter votre code à la recherche d'erreurs à l'aide de l'analyse statique - existe-t-il donc un moyen sensé de gérer cela en PHP?
Un exemple plus complet du problème est:
class StoneItem extends Item{}
class WoodItem extends Item{}
class WoodProcessedItem extends ProcessedItem {
function __construct(WoodItem $woodItem){}
}
class StoneProcessedItem extends ProcessedItem{
function __construct(StoneItem $stoneItem){}
}
abstract class AbstractProcessor {
abstract function processItem(Item $item);
function processAndBoxItem(Box $box, Item $item) {
$processedItem = $this->processItem($item);
$box->insertItem($item);
}
//Lots of other functions that can call processItem
}
class WoodProcessor extends AbstractProcessor {
function processItem(Item $item) {
return new ProcessedWoodItem($item); //This has an inspection error
}
}
class StoneProcessor extends AbstractProcessor {
function processItem(Item $item) {
return new ProcessedStoneItem($item);//This has an inspection error
}
}
Parce que je passe juste un Item
to new ProcessedWoodItem($item)
et qu'il attend un WoodItem comme paramètre, l'inspection du code suggère qu'il y a une erreur.