我在理解Liskov替代原理时遇到了一些困难,并且想知道以下代码是否违反Liskov替代原理?
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?
我不确定,想知道我的假设是否正确
子类的行为不必与基类相同。它必须执行基类的合同。
[不幸的是,您没有记录基类的合同,所以我不能说它是否正确。如果是这样:
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
。
您作为工程师的工作是确保兑现这些诺言。