код нарушает принцип замены Лискова?
Мне сложно понять принцип замещения Лискова, и мне было интересно, нарушает ли следующий код принцип замещения Лискова?
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?
Я не совсем уверен, и мне было интересно, верно ли мое предположение
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
Это Task
.
Ваша задача как инженера - обеспечивать выполнение этих обещаний.