PHP'nin statik kod denetiminin tür tutarlılığını algılamasına izin veren Generics eksikliğine yönelik iyi bir çalışma var mı?
Ben soyut bir sınıf var, ben alt sınıf ve aynı zamanda bir yöntem bir tür bir parametre alarak, bu parametrenin bir alt sınıf olan bir parametre almak için değişir zorlamak istiyorum.
abstract class AbstractProcessor {
abstract function processItem(Item $item);
}
class WoodProcessor extends AbstractProcessor {
function processItem(WoodItem $item){}
}
PHP'de buna izin verilmez, çünkü izin verilmeyen yöntem imzasını değiştirir. Java tarzı jenerikler ile aşağıdakileri yapabilirsiniz:
abstract class AbstractProcessor<T> {
abstract function processItem(T $item);
}
class WoodProcessor extends AbstractProcessor<WoodItem> {
function processItem(WoodItem $item);
}
Ama belli ki PHP bunları desteklemiyor.
Google bu sorun için, kullanıcılar instanceof
çalışma zamanında hataları kontrol etmek için kullanmayı önerir.
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");
}
}
}
Ancak bu sadece çalışma zamanında çalışır, statik analiz kullanarak kodunuzu kontrol etmenize izin vermez - bu yüzden PHP'de bunu ele almanın herhangi bir mantıklı yolu var mı?
Sorunun daha eksiksiz bir örneği:
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
}
}
Çünkü sadece bir Item
için new ProcessedWoodItem($item)
geçiyorum ve parametre olarak bir WoodItem bekliyor, kod denetimi bir hata olduğunu gösterir.