您可以尝试创建自己的集合类型,它可以验证所有东西都是车辆,但也会强制它们都是同一类型的车辆。
<?php
class Vehicle {}
class Car extends Vehicle {}
class SUV extends Vehicle {}
// This doesn't need to be an SplDoublyLinkedList, it's just
// a convenient datastructure to demo with
class VehicleCollection extends SplDoublyLinkedList
{
public function add($index, Vehicle $obj)
{
$this->validateType($obj);
parent::add($index, $obj);
}
public function push(Vehicle $obj)
{
$this->validateType($obj);
parent::push($obj);
}
protected function validateType($obj)
{
// If we have anything in here, ensure next is the same vehicle type
if (!($this->isEmpty() || $this->top() instanceof $obj)) {
throw new InvalidArgumentException('Argument passed to ' . __CLASS__ . '::' . __FUNCTION__ . ' must all be instances of same type.');
}
}
}
// Make a new collection
$col = new VehicleCollection();
// Let's have a couple cars
$car = new Car;
$car2 = new Car;
// And an SUV
$suv = new SUV;
// Let's add our cars
$col->push($car);
$col->push($car2);
var_dump($col);
/* Collection right now:
class VehicleCollection#1 (2) {
private $flags =>
int(0)
private $dllist =>
array(2) {
[0] =>
class Car#2 (0) {
}
[1] =>
class Car#3 (0) {
}
}
}
*/
// Now we try to add an SUV
$col->push($suv);
// and get this:
// PHP Fatal error: Uncaught exception 'InvalidArgumentException' with message 'Argument passed to VehicleCollection::validateType must all be instances of same type.'
如果您进一步扩展,这具有额外的好处,例如做了一个class SportsCar extends Car {},SportsCar可以加入你的收藏。
有人指出我可能误解了您的问题。如果您只是想过滤一个数组,这将成为一个更简单的问题。如果是这样的话,我什至不会费心去实现一个特殊的类——只需将一个闭包传递给array_filter,它非常易读,并且在其他地方也很容易遵循:
$vehicles = [$car, $suv, $car2];
$cars = array_filter($vehicles, function($vehicle) { return $vehicle instanceof Car; });
$suvs = array_filter($vehicles, function($vehicle) { return $vehicle instanceof SUV; });
因此,在该示例中,车辆数组有一辆 SUV,过滤后,$cars 数组只有汽车。如果你想让它成为一个类方法,你可以按照以下方式做一些事情:
public function getAllOfType($type)
{
return array_filter(
$this->vehicles,
function($vehicle) { return is_a($vehicle, $type); }
);
}
然后只从您的收藏中获取汽车:
$cars = $myVehicleCollection->getAllOfType('Car');