код нарушает принцип замены Лискова?

Мне трудно понять принцип замещения Лискова, и мне было интересно, нарушает ли следующий код принцип замещения Лискова?

public class Task {

     String status = "Ready"; // One of "Ready", "Started", and "Closed"

     public void setStatus(String newStatus) {
          status = newStatus;
     }
     public void cancel() {
          status = "Closed";
     }
}
public class ProjectTask extends Task {

     @Override
     public void cancel() {
          if (status.equals("Started")) {
               throw new RuntimeException("Cannot cancel a started project task.");
          }

          super.cancel();
     }
}

Я думаю, что это так, потому что подкласс не ведет себя как базовый класс при его замене, а также потому, что он генерирует исключение RunTimeException?

Я не совсем уверен, и мне было интересно, правильно ли мое предположение


person Kwa Kao    schedule 14.12.2019    source источник


Ответы (1)


Подкласс не должен вести себя так же, как базовый класс. Он должен реализовать контракт базового класса.

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

public class Task {
    ...

    /**
     * Attempt to cancel the task.
     *
     * @throws RuntimeException if the task is not in a cancellable state
     */
    public void cancel() {
        status = "Closed";
    }
}

... тогда все в порядке.

Контракт означает, что любой, кто вызывает Task.cancel, должен ожидать исключения.

Видите ли, LSP - это не только то, что делает базовый класс или что делает подкласс. Речь идет о коде, который использует эти вещи.

LSP говорит, что когда метод или конструктор объявляется для принятия Task в качестве аргумента, тогда объявление обещает, что он работает не только с прямыми Task реализациями, но и со всеми допустимыми реализациями подклассов, потому что ProjectTask IS Task.

Ваша задача как инженера - следить за тем, чтобы эти обещания были выполнены.

person Matt Timmermans    schedule 14.12.2019
comment
Итак, если все задачи должны быть отменены в любом состоянии, тогда будет ли задача проекта нарушать LSP? - person Kwa Kao; 14.12.2019
comment
Да, в самом деле. Или если Task.cancel должен завершиться неудачей без исключения для задач, которые нельзя отменить - person Matt Timmermans; 14.12.2019