Вы можете попробовать создать свой собственный тип коллекции, который подтверждает, что все это транспортное средство, но также обеспечивает, чтобы все они были одним и тем же типом транспортного средства.
<?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; });
Таким образом, в этом примере, массив у транспортных средств есть внедорожник, и после фильтрования в массиве $ cars есть только автомобили. Если вы хотите, чтобы сделать этот метод класса, вы могли бы сделать что-то вдоль линий:
public function getAllOfType($type)
{
return array_filter(
$this->vehicles,
function($vehicle) { return is_a($vehicle, $type); }
);
}
Тогда, чтобы захватить только автомобили из вашей коллекции:
$cars = $myVehicleCollection->getAllOfType('Car');
не создаются специализированные классы коллекций, но только один, использующий базовый класс автомобиля.Все остальное - вопрос о геттерах и сеттерах. Другие языки предлагают шаблонные классы или шаблоны классов для такого материала, php не имеет такой вещи. Но опять же вам это не понадобится в ситуации, когда вы хотите использовать php. – arkascha
Вы можете хранить массивы, содержащие экземпляры разных типов, каждый из которых наследуется от «Vehicle». – halfer
Я думаю, что здесь вам нужно использовать инъекцию зависимости - образец дизайна. Может быть, это решит вашу проблему. –