PHPのGenericsの欠如に対して、静的コード検査で型の一貫性を検出できる適切な回避策はありますか?
サブクラスを作成する抽象クラスがあり、メソッドの1つが1つの型のパラメーターの取得から、そのパラメーターのサブクラスであるパラメーターの取得に変更されるように強制します。
abstract class AbstractProcessor {
abstract function processItem(Item $item);
}
class WoodProcessor extends AbstractProcessor {
function processItem(WoodItem $item){}
}
これは、許可されていないメソッドシグネチャを変更するため、PHPでは許可されていません。Javaスタイルのジェネリックスを使用すると、次のようなことができます。
abstract class AbstractProcessor<T> {
abstract function processItem(T $item);
}
class WoodProcessor extends AbstractProcessor<WoodItem> {
function processItem(WoodItem $item);
}
しかし、PHPはこれらをサポートしていません。
この問題のためのグーグル、人々はinstanceof
実行時にエラーをチェックするために使用することをお勧めします例えば
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");
}
}
}
しかし、これは実行時にのみ機能し、静的分析を使用してコードのエラーを検査することはできません。PHPでこれを処理する賢明な方法はありますか?
問題のより完全な例は次のとおりです。
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
}
}
Item
to だけを渡していnew ProcessedWoodItem($item)
て、パラメーターとしてWoodItemを期待しているため、コードインスペクションはエラーがあることを示唆しています。