Có công việc nào phù hợp với việc thiếu Generics của PHP cho phép kiểm tra mã tĩnh để phát hiện tính nhất quán của loại không?
Tôi có một lớp trừu tượng, tôi muốn lớp con và cũng thực thi rằng một trong các phương thức thay đổi từ lấy tham số của một loại, sang lấy tham số là lớp con của tham số đó.
abstract class AbstractProcessor {
abstract function processItem(Item $item);
}
class WoodProcessor extends AbstractProcessor {
function processItem(WoodItem $item){}
}
Điều này không được phép trong PHP vì nó thay đổi chữ ký phương thức không được phép. Với các kiểu chung Java, bạn có thể làm một cái gì đó như:
abstract class AbstractProcessor<T> {
abstract function processItem(T $item);
}
class WoodProcessor extends AbstractProcessor<WoodItem> {
function processItem(WoodItem $item);
}
Nhưng rõ ràng PHP không hỗ trợ những thứ đó.
Google cho vấn đề này, mọi người đề nghị sử dụng instanceof
để kiểm tra lỗi trong thời gian chạy, vd
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");
}
}
}
Nhưng điều đó chỉ hoạt động trong thời gian chạy, nó không cho phép bạn kiểm tra lỗi mã của mình bằng phân tích tĩnh - vậy có cách xử lý nào hợp lý trong PHP không?
Một ví dụ đầy đủ hơn về vấn đề là:
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
}
}
Bởi vì tôi chỉ Item
chuyển đến new ProcessedWoodItem($item)
và nó mong đợi WoodItem là tham số, việc kiểm tra mã cho thấy có lỗi.