PHP: по какой причине некоторые люди «подделывают» абстрактные методы, создавая исключение исключительно в теле? - PullRequest
0 голосов
/ 17 января 2019

В последнее время я часто вижу код, подобный следующему (этот пример взят из Symfony):

protected function execute(InputInterface $input, OutputInterface $output)
{
    throw new LogicException('You must override the execute() method in the concrete command class.');
}

В чем здесь преимущество, если просто пометить метод как abstract?

Какая выгода для ...

  1. ... автор библиотеки?
  2. ... пользователь библиотеки?

Я уже нашел подобный вопрос для Java ( Подделка абстрактных методов с использованием исключений в Java ), но он не очень помог, поскольку его ответы - явные предположения и мнения.

Ответы [ 3 ]

0 голосов
/ 17 января 2019

В данном конкретном случае комментарии объясняют:

/**
 * 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, поэтому в нем может быть один из тех «казавшихся в то время хорошей идеей» кусочков функциональности.

0 голосов
/ 17 января 2019

Возможный вариант использования - дополнительные методы.Если вы сделаете его абстрактным, тогда все дочерние классы должны его реализовать:

abstract class Database
{
    abstract public function export();
}

class MySQL extends Database
{
}

Неустранимая ошибка: класс MySQL содержит 1 абстрактный метод и поэтому должен быть объявлен как абстрактный или реализовывать остальные методы (Database ::export)

Если вы создаете обычный метод, тогда дочерние классы должны реализовывать метод только в том случае, если они планируют его поддерживать.

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 не поддерживает экспорт

0 голосов
/ 17 января 2019

только абстрактные классы могут иметь абстрактные методы.

Вы не можете создавать объекты из абстрактных классов.

Все абстрактные методы должны быть реализованы в неабстрактных классах.

Построенный пример:

Представьте себе следующее:

abstract class Repository {
    public abstract function read();
    public abstract function write($object);
    public abstract function delete($object);
    public function connection() {
        //this is implemented for you by the framework so you don't have to do it every time
    }

Теперь вы хотите реализовать репозиторий для регистрации действий пользователя (вход в систему, выход из системы, ...)

Вы не хотите, чтобы какие-либо из этих записей были удалены, и именно тогда вы не хотите реализовывать функцию delete. Но вы должны это сделать, потому что ваш UserActionRepository не является абстрактным, потому что вам действительно нужны его экземпляры. вот когда вы бросаете исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...