我有两个类,A和B,其中B扩展了A。我遇到了一个问题,B引入了一个附加功能,该功能附带了一个异常ExceptionC
,该异常不以任何形式应用于A,但除非A指定它为throws ExceptionC
,否则它不会编译。我知道这是故意的(因为利斯科夫替代原则)。我的问题有两个:
- 利斯科夫替代原则背后的原因是什么?如果B扩展了A,难道它不应该添加更多的功能,从而添加例外吗
- 有什么更好的方法可以做到这一点?在超类中添加一个不适用的异常感觉是错误的
具体情况:
我正在用Java编写一个终极Tic-Tac-Toe的实现。基本上取一个井字网格,并用井字网格填充,如下所示:
| | # | | # | |
| | # | | # | |
| | # | | # | |
#################
| | # | | # | |
| | # | | # | |
| | # | | # | |
#################
| | # | | # | |
| | # | | # | |
| | # | | # | |
你从中心开始,X在这个网格中的任何位置,O都在对应于较大网格的网格中,所以在两次移动后,它可能看起来像这样:
| |O# | | # | |
| | # | | # | |
| | # | | # | |
#################
| | #X| | # | |
| | # | | # | |
| | # | | # | |
#################
| | # | | # | |
| | # | | # | |
| | # | | # | |
如果目标网格已满或已经获胜,下一个人可以选择进入哪个网格。
我有两个普通类、两个异常类和一个接口。
- TTTBoard实现Board
- UltimateTTTB板扩展TTT板实现板
- TTTBoard.move抛出LocationTakeException
- UltimateTTTBoard.move引发LocationTakeException、TargetBoardFullException
请注意,在标准井字游戏中,只有一块板,因此TargetBoardFullException完全不适用。
我做错了吗?我不应该对此使用例外吗?
以下代码显示了Java不允许更改合同的原因:
class A {
public void method() {
// do something
}
}
class B extends A {
public void method() throws IOException { // <- compile error here
// do something and throw and exception
}
}
class App {
public static void main(String[] args) {
A a = new B();
a.method(); // to try or not to try, that's the question now.
}
}
当然,它不会编译。但是,如果是这样的话,我们是否必须在主方法中捕获IOException(因为它是B
实例)(因为我们在接口上调用该方法)?