Возможно, kwcombinatorics может оказать некоторую помощь (см. пример на домашней странице):
Библиотека KwCombinatorics - это 3 класса, которые предоставляют 3 разных способа создания упорядоченных (ранжированных ) списки комбинаций чисел. Эти комбинаторики полезны для тестирования программного обеспечения, что позволяет генерировать различные типы возможных комбинаций ввода. Другие виды использования включают решение математических задач и азартных игр.
blockquote>
Возможный вариант использования - дополнительные методы. Если вы сделаете его абстрактным, то все дочерние классы должны будут его реализовать:
abstract class Database
{
abstract public function export();
}
class MySQL extends Database
{
}
Неустранимая ошибка: класс MySQL содержит 1 абстрактный метод и поэтому должен быть объявлен как абстрактный или реализовать остальные методы (Database :: export)
blockquote>Если вы создаете обычный метод, тогда дочерние классы должны реализовывать метод только в том случае, если они планируют его поддерживать.
abstract class Database { public function export(){ throw new \LogicException(__CLASS__ . ' driver does not support ' . __FUNCTION__); } } class MySQL extends Database { }
... но вы получите приятную ошибку, если попытаетесь ее использовать:
$s = new MySQL(); $s->export();
Неустранимая ошибка: необработанное исключение 'LogicException': драйвер MySQL не поддерживает экспорт [ 117] blockquote>
В данном конкретном случае комментарии объясняют:
/**
* Executes the current command.
*
* This method is not abstract because you can use this class
* as a concrete class. In this case, instead of defining the
* execute() method, you set the code to execute by passing
* a Closure to the setCode() method.
*
* @return int|null null or 0 if everything went fine, or an error code
*
* @throws LogicException When this abstract method is not implemented
*
* @see setCode()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
throw new LogicException('You must override the execute() method in the concrete command class.');
}
Вы можете поспорить с общим дизайном, так как он, возможно, немного хакерский, но он хорошо работает на практике. Взгляните на Command :: run, чтобы увидеть, где принято решение использовать замыкание или выполнить. Немного нишевый случай, если не сказать больше.
Я знаю, что многое из этого обсуждалось в комментариях к другому ответу, но я подумал, что это может помочь в обобщении. Я также провел быстрый поиск по коду фреймворка Symfony, чтобы увидеть, где был использован подход замыкания. Ничего не нашел. Поддержка замыкания полностью восходит к исходному выпуску 2.0, поэтому у него может быть один из тех «казавшихся в то время хорошей идеей» кусочков функциональности.