มีการทำงานที่ดีในการขาด Generics ของ PHP ที่ช่วยให้การตรวจสอบรหัสคงที่เพื่อตรวจสอบความสอดคล้องของประเภท?
ฉันมีคลาสนามธรรมที่ฉันต้องการ sub-class และบังคับใช้วิธีการอย่างใดอย่างหนึ่งเปลี่ยนจากการรับพารามิเตอร์ชนิดหนึ่งการรับพารามิเตอร์ซึ่งเป็น sub-class ของพารามิเตอร์นั้น
abstract class AbstractProcessor {
abstract function processItem(Item $item);
}
class WoodProcessor extends AbstractProcessor {
function processItem(WoodItem $item){}
}
สิ่งนี้ไม่ได้รับอนุญาตใน PHP เพราะมันเปลี่ยนลายเซ็นวิธีที่ไม่ได้รับอนุญาต ด้วย generics สไตล์ Java คุณสามารถทำสิ่งที่ชอบ:
abstract class AbstractProcessor<T> {
abstract function processItem(T $item);
}
class WoodProcessor extends AbstractProcessor<WoodItem> {
function processItem(WoodItem $item);
}
แต่เห็นได้ชัดว่า PHP ไม่สนับสนุนสิ่งเหล่านั้น
Google สำหรับปัญหานี้ผู้คนแนะนำให้ใช้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
ไปnew ProcessedWoodItem($item)
และคาดว่า WoodItem เป็นพารามิเตอร์ที่ตรวจสอบรหัสที่แสดงให้เห็นมีข้อผิดพลาด