Apakah ada pekerjaan yang layak untuk kurangnya PHP Generics yang memungkinkan pemeriksaan kode statis untuk mendeteksi konsistensi jenis?
Saya memiliki kelas abstrak, yang ingin saya sub-kelas dan juga menegakkan bahwa salah satu metode berubah dari mengambil parameter dari satu jenis, untuk mengambil parameter yang merupakan sub-kelas dari parameter itu.
abstract class AbstractProcessor {
abstract function processItem(Item $item);
}
class WoodProcessor extends AbstractProcessor {
function processItem(WoodItem $item){}
}
Ini tidak diizinkan dalam PHP karena itu mengubah metode tanda tangan yang tidak diizinkan. Dengan generik gaya Java, Anda dapat melakukan sesuatu seperti:
abstract class AbstractProcessor<T> {
abstract function processItem(T $item);
}
class WoodProcessor extends AbstractProcessor<WoodItem> {
function processItem(WoodItem $item);
}
Tapi jelas PHP tidak mendukung itu.
Google untuk masalah ini, orang menyarankan menggunakan instanceof
untuk memeriksa kesalahan pada saat run-time misalnya
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");
}
}
}
Tapi itu hanya berfungsi saat runtime, itu tidak memungkinkan Anda untuk memeriksa kode Anda untuk kesalahan menggunakan analisis statis - jadi apakah ada cara yang masuk akal untuk menangani ini di PHP?
Contoh masalah yang lebih lengkap adalah:
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
}
}
Karena saya melewati hanya Item
ke new ProcessedWoodItem($item)
dan mengharapkan WoodItem sebagai parameter, pemeriksaan kode menunjukkan ada kesalahan.